How do I reverse the Mod operator - vb.net

I have a simple function that handles overflows with modulus operator
Private Function RandomizeBlock(seed As Integer, ByVal block() As Byte) As Byte()
Dim Generator As System.Random = New System.Random(seed)
Dim newblock(255) As Byte
Dim i As Integer = 0
For i = 0 To block.Length - 1
newblock(i) = (block(i) + Generator.Next(0, 256)) Mod 256
Next
Return newblock
End Function
How do I undo the randomization done to a block?
I know mod works like this:
253,254,255,0,1,2,3,4 overwraps on 0.
Do can I find the inverse of reverse here?
rndValue = Generator.Next(0, 256)
reverse_1 = ((256 - rndValue) + block(i)) Mod 256
reverse_2 = ((256 + rndValue) - block(i)) Mod 256

If you know the random value, then reconstructing the original value is very simple.
You just have to keep in mind that working modulo p, you don't have actual numbers but remainder classes. The first p natural numbers are usually used as the representatives of these classes. Luckily, subtraction and addition are perfectly compatible with remainder classes.
The Mod implementation of VB converts any positive number to the representative of its remainder class. However, it can not do it on negative numbers. You have to do it on your own.
Long story short, this is the code:
Dim reverse As Integer = block(i) - rndValue;
If reverse < 0 Then reverse = reverse + 256 'Convert to representative of remainder class

Related

VB .NET Convert string to array of bytes without converting the characters

I'm trying to split a string of 32 numerical characters into a 16 length Array of Byte and each value has to stay numerical
from "70033023311330000000004195081460" to array {&H_70, &H_03, &H_30, &H_23, ..}
I've tried multiple stuff but each time either it's the conversion that's wrong or I can't find the appropriate combination of functions to implement it.
'it splits but per 1 character only instead of two
str.Select(Function(n) Convert.ToByte(n, 10)).ToArray
'I also tried looping but then the leading zero disappears and the output is a string converted to HEX which is also not what I want.
Function ConvertStringToHexBinary(str As String) As Byte()
Dim arr(15) As Byte
Dim k = 0
For i As Integer = 0 To str.Length - 1
arr(k) = str(i) & str(i + 1)
k += 1
i += 1
Next
Return arr
End Function
Anyone got any suggestion what to do?
G3nt_M3caj's use of LINQ might be.. er.. appealing to the LINQ lovers but it's horrifically inefficient. LINQ is a hammer; not everything is a nail.
This one is about 3 times faster than the LINQ version:
Dim str As String = "70033023311330000000004195081460"
Dim byt(str.Length/2) as Byte
For i = 0 to str.Length - 1 Step 2
byt(i/2) = Convert.ToByte(str.Substring(i, 2))
Next i
And this one, which does it all with math and doesn't do any new stringing at all is just under 3 times faster than the above (making it around 9 times faster than the LINQ version):
Dim str As String = "70033023311330000000004195081460"
Dim byt(str.Length / 2) As Byte
For i = 0 To str.Length - 1
If i Mod 2 = 0 Then
byt(i / 2) = (Convert.ToByte(str(i)) - &H30) * &HA
Else
byt(i / 2) += Convert.ToByte(str(i)) - &H30
End If
Next i
Of the two, I prefer the stringy version because it's easier to read and work out what's going on - another advantage loops approaches often have over a LINQ approach
Do you need something like this?
Dim str As String = "70033023311330000000004195081460"
Dim mBytes() As Byte = str.
Select(Function(x, n) New With {x, n}).
GroupBy(Function(x) x.n \ 2, Function(x) x.x).
Select(Function(y) Convert.ToByte(New String(y.ToArray()), 10)).ToArray

Convert 32-bit signed integer to 64-bit integer while preserving the exact bits

I have a 32-bit value that is stored in the VB.Net type Integer (i.e. Int32.) I am only interested in the bits - not the numerical value. Sometimes the 32nd bit is a one which is interpreted as a negative number. My goal is to reverse the actual bits. My original data is encoded into bits right-to-left (LSB right-most) and is read back in left-to-right (MSB left-most.) I am adapting someone else's code and design. One thought I had was maybe to convert to a long temporarily but I don't know how to do that and preserve the 32nd bit correctly.
Public Shared Function ReverseBits32(ByVal n As Integer) As Integer
Dim result As Integer = 0
For i As Integer = 0 To 32 - 1
result = result * 2 + n Mod 2
n = n >> 1 'n Or 2
Next
Return result
End Function
If you had a method to reverse the bits of a byte you could apply it four times to the bytes of an integer. A little research finds Bit Twiddling Hacks.
Module Module1
Sub ShowBits(a As Integer)
Dim aa = BitConverter.GetBytes(a)
Console.WriteLine(String.Join(" ", aa.Select(Function(b) Convert.ToString(b, 2).PadLeft(8, "0"c))))
End Sub
Function ReverseBits(b As Byte) As Byte
' From https://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
Dim c = CULng(b)
Return CByte((((c * &H802UL And &H22110UL) Or (c * &H8020UL And &H88440UL)) * &H10101UL >> 16) And &HFFUL)
End Function
Function ReverseBits(a As Integer) As Integer
Dim bb = BitConverter.GetBytes(a)
Dim cc(3) As Byte
For i = 0 To 3
cc(3 - i) = ReverseBits(bb(i))
Next
Return BitConverter.ToInt32(cc, 0)
End Function
Sub Main()
Dim y = -762334566
ShowBits(y)
y = ReverseBits(y)
ShowBits(y)
Console.ReadLine()
End Sub
End Module
Output from test value:
10011010 10110010 10001111 11010010
01001011 11110001 01001101 01011001
I used the "no 64-bit" method because it is written for a language where arithmetic overflow is ignored - the methods using 64-bit operations rely on that but it is not the default for VB.NET.

Add integer to another integer in vb.net?

How can I add an integer to another integer in vb.net?
This is what I need to do:
Given integer: 2187 ->
Converted integer: 2018
I need to add a 0 in between the first and second number, and drop the last digit. This will give me the year.
Here is the code that I have:
Protected Function GetYear(ByVal term As Integer) As Integer
Dim termYear As String = Convert.ToString(term)
termYear.Substring(0, 2)
termYear.Insert(1, "0")
Dim convertedYear As Integer
Int32.TryParse(termYear.ToString, convertedYear)
convertedYear = convertedYear / 10
Return convertedYear
End Function
In general strings are immutable. So you'd have to create a new string out of the addition of substrings. Check this possible solution.
Function GetYear(ByVal term As Integer) As Integer
Dim termYear As String = Convert.ToString(term, Globalization.CultureInfo.InvariantCulture)
Dim result As String = termYear.Substring(0, 1) + "0" + termYear.Substring(1, 2)
Return Int32.Parse(result)
End Function
Strings are immutable, when you do any changes with one of their method, you need to get the returned string.
termYear = termYear.Insert(1, "0")
This question deserves a math based solution. The below code specifies the zero insertion point relative to the number's right side instead of the left as stated in the problem statement. So for a 4 digit number the insertion point is 3 versus 2. It also allows you to change the insertion point.
Private Function GetYear(ByVal term As Integer, Optional zeroDigitPosition As Integer = 3) As Integer
If zeroDigitPosition > 0 Then
Dim divisor As Integer = 1
For i As Integer = 1 To zeroDigitPosition - 1
divisor *= 10
Next
Dim ret As Integer = term \ 10 ' drop one's place digit, remaining digits shift to right
Dim rightShiftedDigits As Integer = ret Mod divisor
Dim remainder As Integer = Math.DivRem(ret, divisor, rightShiftedDigits)
' shift the remainder to the left by divisor * 10
' (remember first right shift invplved \ 10) and add
' rightShiftedDigits to yield result
Return (remainder * divisor * 10) + rightShiftedDigits
Else
Throw New ArgumentOutOfRangeException("zeroDigitPosition must be greater then zero")
End If
End Function

Mod with Doubles

Am I doing something wrong or does the VBA Mod operator actually not work with floating point values like Doubles?
So I've always sort of assumed that the VBA Mod operator would work with Doubles based on the VB documentation, but in trying to figure out why my rounding function doesn't work, I found some unexpected Mod behavior.
Here is my code:
Public Function RoundUp(num As Double, Optional nearest As Double = 1)
RoundUp = ((num \ nearest) - ((num Mod nearest) > 0)) * nearest
End Function
RoundUp(12.34) returns 12 instead of 13 so I dug a little deeper and found that:
12.5 Mod 1 returns 0 with the return type of Long, whereas I had expected 0.5 with a type of Double.
Conclusion
As #ckuhn203 points out in his answer, according to the VBA specification,
The modulus, or remainder, operator divides number1 by number2
(rounding floating-point numbers to integers) and returns only the
remainder as result.
And
Usually, the data type of result is a Byte, Byte variant, Integer,
Integer variant, Long, or Variant containing a Long, regardless of
whether or not result is a whole number. Any fractional portion is
truncated.
For my purposes, I need a floating point modulo and so I have decided to use the following:
Public Function FMod(a As Double, b As Double) As Double
FMod = a - Fix(a / b) * b
'http://en.wikipedia.org/wiki/Machine_epsilon
'Unfortunately, this function can only be accurate when `a / b` is outside [-2.22E-16,+2.22E-16]
'Without this correction, FMod(.66, .06) = 5.55111512312578E-17 when it should be 0
If FMod >= -2 ^ -52 And FMod <= 2 ^ -52 Then '+/- 2.22E-16
FMod = 0
End If
End Function
Here are some examples:
FMod(12.5, 1) = 0.5
FMod(5.3, 2) = 1.3
FMod(18.5, 4.2) = 1.7
Using this in my rounding function solves my particular issue.
According to the VB6/VBA documentation
The modulus, or remainder, operator divides number1 by number2
(rounding floating-point numbers to integers) and returns only the
remainder as result. For example, in the following expression, A
(result) equals 5. A = 19 Mod 6.7 Usually, the data type of result is
a Byte, Byte variant, Integer, Integer variant, Long, or Variant
containing a Long, regardless of whether or not result is a whole
number. Any fractional portion is truncated. However, if any
expression is Null, result is Null. Any expression that is Empty is
treated as 0.
Remember, mod returns the remainder of the division. Any integer mod 1 = 0.
debug.print 12 mod 1
'12/1 = 12 r 0
The real culprit here though is that vba truncates (rounds down) the double to an integer before performing the modulo.
?13 mod 10
'==>3
?12.5 mod 10
'==>2
debug.print 12.5 mod 1
'vba truncates 12.5 to 12
debug.print 12 mod 1
'==> 0
I believe that the Mod operator calculates with long type only. The link that you provided is for VB.Net, which is not the same as the VBA you use in MSAccess.
The operator in VBA appears to accept a double type, but simply converts it to a long internally.
This test yielded a result of 1.
9 Mod 4.5
This test yielded a result of 0.
8 Mod 4.5
As a work around your can do some simple math on the values. To get two decimal of precision just multiply the input values by 100 and then divide the result by 100.
result = (123.45*100 Mod 1*100)/100
result = (12345 Mod 100)/100
result = 0.45
I'm late to the party, but just incase this answer is still helpful to someone.
Try This in VBS:
Option Explicit
Call Main()
Sub Main()
WScript.Echo CStr(Is_Rest_Of_Divide_Equal_To_Zero(506.25, 1.5625))
End Sub
Function Is_Rest_Of_Divide_Equal_To_Zero(Divident, Divisor)
Dim Result
Dim DivideResult
If Divident > Divisor Then
DivideResult = Round(Divident/Divisor, 0)
If (DivideResult * Divisor) > Divident Then
Result = False
ElseIf (DivideResult * Divisor) = Divident Then
Result = True
ElseIf (DivideResult * Divisor) < Divident Then
Result = False
End If
ElseIf Divident = Divisor Then
Result = True
ElseIf Divident < Divisor Then
Result = False
End If
Is_Rest_Of_Divide_Equal_To_Zero = Result
End Function
Public Function Modi(d as double) as double
Modi = d - Int(d)
End Function
Dim myDoule as Double
myDoule = 1.99999
Debug.Print Modi(myDoule)
0.99999

How to reverse this algorithm to get back the original text? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
Can anyone please explain with the easy coding how to reverse this algorithm so that I get back the original text string?
Public Function CreateIntChecksum(ByVal s As String) As Integer
Dim r As Integer = 0
For i As Integer = 0 To (s.Length() - 1)
Dim bchar As Byte = Convert.ToByte(s(i))
r = bchar + ((r << 5) - r)
Next
Return r
End Function
Although it is impossible to find the original text, it is possible find a preimage easily. The crucial point is
r = bchar + ((r << 5) - r)
which is equivalent to
r = bchar + r*31
Therefore, the hash encodes the string in base-31. To find a preimage, just rewrite the integer in base 31.
For instance, if the result is 3456, we know 3456 = 3 × 312 + 18 × 31 + 15, so one possible original text is "\x03\x12\x0f". Of course, we could rearrange the numbers to give 110 × 31 + 46 ("n.") or 109 × 31 + 77 ("mM") etc, which shows there is no unique preimage.
You can't. What you have here is a Checksum, which is a basic hashing function. The the whole point of a hashing function is that it is irreversible. Hashing functions map a set of inputs (usually infinite) to a smaller set of outputs - so multiple inputs can end up with the same output, and thus this makes reversing a hash impossible (assuming the hash is correctly done). This is why they are used to store passwords - there is no way to read a hash and go "Oh, that is password XYZ".
One way of trying to find out the original value is to use a Rainbow Table. This is merely a massive table of inputs and their equivalent hashed (or in this case checksummed) values. If you have the hashed value of your unknown string you can search for it in the table and get the set of possible inputs. This is not a way to reverse a hash function, which is impossible; it is merely a brute force guessing method. Note also that in this case (assuming the hashing function is not biased) there are an infinite number of strings that match each checksummed value, as a visual basic string can be of arbitrary length. This would make a rainbow table for this very impractical - you could cover the set of probably inputs for a hashing (as most normal users won't enter more than a 10 character code), but nothing stops the user using a 67 character code, or 109, or...
Read the wikipedia articles for Hash Functions, Checksums and Rainbow Tables.
how to reverse this algorithm so that I get back the original text string?
You can't, by design.
This is a (simple) checksum or hashing function.
Take a look at the size of the information going in and out: the function transforms a string s of arbitrary length into a 32-bit Integer. For each integer value there will be many input strings that will yield that result.
Edit: Apparently you want a shuffling algorithm. Maybe take a look at ROT13. Be advised this is not a (very) safe form of encryption.
You simply can't reverse it. It's a checksum which is not reversible.
You can't. If nothing else, then simply because Integer contains only 32 bits of data and String can have any length.
First of all the code as posted will throw an exception for anything but the shortest of strings.
The following code includes the OP's original code, plus a simple checksum, and a guess at how the checksum might be used.
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim buffer() As Byte
Dim tstString As String = "Calculate a checksum for a given string"
Dim chkSumFix As Integer = CreateIntChecksumFixed(tstString) 'get a checksum
buffer = SendPacket(tstString, chkSumFix) 'create a byte buffer to send
tstString = decodePacket(buffer)
'do the same using the OP's original code
Dim chkSum As Integer = CreateIntChecksum(tstString) 'error
buffer = SendPacket(tstString, chkSum)
End Sub
'OP
Public Function CreateIntChecksum(ByVal s As String) As Integer
Dim r As Integer = 0
For i As Integer = 0 To (s.Length() - 1)
Dim bchar As Byte = Convert.ToByte(s(i))
r = bchar + ((r << 5) - r)
Next
Return r
End Function
'a very simple checksum
Public Function CreateIntChecksumFixed(ByVal s As String) As Integer
Dim r As Integer = 0
For i As Integer = 0 To (s.Length() - 1)
Dim bchar As Byte = Convert.ToByte(s(i))
r = (r And &HFFFF) + bchar
Next
Return r
End Function
Private Function SendPacket(ByVal aString As String, _
ByVal aChecksum As Integer) As Byte()
'construct a packet to be sent
'Packet format
'returns a byte buffer
'byte(0 -3) = length of original string - use BitConverter.ToInt32 to extract
'byte(4-n) = original string. n = (4 + string length) - 1
'byte(n + 1, n + 2, n + 3, n + 4) = checksum
Dim length As Integer
Dim retV As New List(Of Byte)
retV.AddRange(System.Text.Encoding.ASCII.GetBytes(aString)) 'add string to packet
length = retV.Count 'get length - use this length in case a different encoding is used
retV.AddRange(BitConverter.GetBytes(aChecksum)) 'add checksum
retV.InsertRange(0, BitConverter.GetBytes(length)) 'insert length at start of packet
Return retV.ToArray
End Function
Private Function decodePacket(ByVal buffer As Byte()) As String
Dim sLen As Integer = BitConverter.ToInt32(buffer, 0)
If sLen + 8 <> buffer.Length Then Throw New ArgumentOutOfRangeException
Dim s As String = System.Text.Encoding.ASCII.GetChars(buffer, 4, sLen)
Dim chksum As Integer = CreateIntChecksumFixed(s)
Dim embeddedChecksum As Integer = BitConverter.ToInt32(buffer, sLen + 4)
If chksum <> embeddedChecksum Then Throw New ArgumentException("Invalid checksum")
Return s
End Function