adler-32 algorithm example Clarity would be great - c#

I am having a hard time understanding what exactly is going on behind this algorithm. So, I have the following code which I believe works for the Wikipedia example. I seem to be having problems matching up the correct outcomes of hex values. While for the wiki example I get the correct hex value, It seems that my int finalValue; is not the correct value.
string fText, fileName, output;
Int32 a = 1 , b = 0;
const int MOD_ADLER = 65521;
const int ADLER_CONST2 = 65536;
private void btnCalculate_Click(object sender, EventArgs e) {
fileName = tbFilePath.Text;
if(fileName != "" && File.Exists(fileName)) {
fText = File.ReadAllText(fileName);
foreach (char i in fText) {
a = ( a + Convert.ToInt32(i)) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
}
int finalValue = (b * ADLER_CONST2 + a);
output = finalValue.ToString("X");
lbValue.Text = output.ToString();
}
else {
MessageBox.Show("This is not a valid filepath, or is a blank file.\n" +
"Please enter a valid file path.");
}
}
I understand that this is not an efficient way to go about this, I am just trying to understand what is really going on under the hood. That way I can create a more efficient algorithm that varies from this.
From my understanding. In my code, the example value a is going to be added the integer (32 bit) value plus its initial value of 1. I do the Mod of the very high prime number, and continue moving through the sub-string of my text file adding up the values until all of the characters have been added up.

Probably this two lines confuse you.
a = ( a + Convert.ToInt32(i)) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
Every char have integer representation. You can check this article. You are changing the value a to be the reminder-> from current value of a + int representetion of the char divided by MOD_ADLER. You can read operator %
What is reminder: 5%2 = 1
After that you are making same thing for b. b is equal to the reminder current value of b+a divided by MOD_ADLER. After you do that multiple times ( number of chars in the string). You have this.
int finalValue = (b * ADLER_CONST2 + a);
output = finalValue.ToString("X");
This converts the final integer value to HEX.

output = finalValue.ToString("X");
The "X" format says generate the hexadecimal represent of the number!
See MSDN Standard Numeric Format Strings

Related

Reading text file with reaping pattern c#

I want to read from a text file a hex number, using the last digit to define my length to read a string, again a number and so on until the line will finish.
using (StreamReader sr = new StreamReader(fileName)){
String line = sr.ReadLine();
string hexText = line.Substring(0,9);
char c = hexText[8];
int con = c - '0'; //saving the value
string myHex = con.ToString("X");
int length = Convert.ToInt32(myHex, 16);
string fieldChars = line.Substring(0, length); //getting the key
string b = line.Substring(c, length); }
so for "5A3F00004olga" the length is correct and 4 (the last hex bit) but for some reason b is not Olga.Why?
Let's take a closer look at your code. You have:
char c = hexText[8];
int con = c - '0'; //saving the value
string myHex = con.ToString("X");
int length = Convert.ToInt32(myHex, 16);
string fieldChars = line.Substring(0, length); //getting the key
string b = line.Substring(c, length);
So c contains the value of the character at position 8. I don't have any idea why you're subtracting '0' from it, and then converting the result back to a string. You could just as easily write:
string myHex = c + "X";
Also, if the value at hexText[8] were 'A', then subtracting '0' would give you 17 rather than the 10 that you expected.
I also don't know what you expect the line that assigns fieldChars to do, but I can pretty much guarantee that it's not doing what you want.
The reason b doesn't contain "olga" is because the substring starting position in this case would be 4 (44 in decimal), and length could be totally wrong as described above.
I think the code you want is:
char c = hexText[8];
string myHex = con.ToString("X");
int length = Convert.ToInt32(myHex, 16);
string b = line.Substring(9, length);
I didn't include fieldChars there because it's unclear to me what you want value you want that variable to hold. If you want the key, then you'd want line.Substring(0, 8); If you want the entire field, including the key, the length, and the text, you'd write line.Substring(0, 9 + length);
As suggested in comments, you can use the C# debugger to walk through your code one line at a time, and inspect variables to see what is happening. That's an excellent way to see the results of the code you write. Better yet is to work a few examples by hand before you start writing code. That way you get a better understanding of what the code is supposed to do. It makes writing correct code a whole lot easier.
If you don't know how to use the debugger, now is the perfect time to learn.
Another way you can see what's happening is to put Console.WriteLine statements after each line. For example:
char c = hexText[8];
Console.WriteLine("c = " + c);
If you do that after each line, or after each important group of lines, displaying the values of important variables, you can see exactly where your program is going off into the weeds.

convert string to integer array C#

I'm a C# newbie learning how to work with arrays. I wrote a small console app that converts binary numbers to their decimal equivalents; however, the sytax I've used seems to be causing the app to - at some point - use the unicode designation of integers instead of the true value of the integer itself, so 1 becomes 49, and 0 becomes 48.
How can I write the app differently to avoid this? Thanks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sandbox
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Key in binary number and press Enter to calculate decimal equivalent");
string inputString = Console.ReadLine();
////This is supposed to change the user input into character array - possible issue here
char[] digitalState = inputString.ToArray();
int exponent = 0;
int numberBase = 2;
int digitIndex = inputString.Length - 1;
int decimalValue = 0;
int intermediateValue = 0;
//Calculates the decimal value of each binary digit by raising two to the power of the position of the digit. The result is then multiplied by the binary digit (i.e. 1 or 0, the "digitalState") to determine whether the result should be accumulated into the final result for the binary number as a whole ("decimalValue").
while (digitIndex > 0 || digitIndex == 0)
{
intermediateValue = (int)Math.Pow(numberBase, exponent) * digitalState[digitIndex]; //The calculation here gives the wrong result, possibly because of the unicode designation vs. true value issue
decimalValue = decimalValue + intermediateValue;
digitIndex--;
exponent++;
}
Console.WriteLine("The decimal equivalent of {0} is {1}", inputString, intermediateValue);
Console.ReadLine();
}
}
}
Simply use the following code
for (int i = 0; i < digitalState.Length; i++)
{
digitalState[i] = (char)(digitalState[i] - 48);
}
After
char[] digitalState = inputString.ToArray();
Note that the value of a character, for example '1' is different from what it represents. As you already noticed '1' is equal to ASCII code 49. When you subtract 48 from its value (49) it becomes 1.
there were two errors: you missed the "-48" and wrote the intermediate instead of the result (last line). Not sure how to unline some parts in the codeblock ;)
intermediateValue = (int)Math.Pow(numberBase, exponent) * (digitalState[digitIndex]-48;
//The calculation here gives the wrong result,
//possibly because of the unicode designation vs. true value issue
decimalValue += intermediateValue;
(.....)
Console.WriteLine("The decimal equivalent of {0} is {1}", inputString, decimalValue);
#CharlesMager says it all. However, I assume this is a homework assignment. So as you said multiplying by the ASCII value is wrong. So just subtract '0' (decimal value 48) from ASCII value.
intermediateValue = (int)Math.Pow(numberBase, exponent)
* ((int)digitalState[digitIndex] - 48);
You code is ugly, there is no need to go backwards from the string. Also using Math.Power is inefficient, shifting (<<) is equivalent for binary powers.
long v = 0;
foreach (var c in inputString)
{
v = (v << 1) + ((int)c - 48);
}
Console.WriteLine("The decimal equivalent of {0} is {1}", inputString, v);
Console.ReadLine();

How to compare two hexadecimal numbers

What is the best way to compare two hexadecimal numbers (that is a string)? For instance,
string a = "3F";
string b = "32";
if (a > b)
MessageBox.Show("a is greater");
Should work. (Assuming > has been properly overloaded).
You can always convert them to ints and compare them that way:
int a = int.Parse("3E", System.Globalization.NumberStyles.HexNumber);
int b = int.Parse("32", System.Globalization.NumberStyles.HexNumber);
if (a > b)
MessageBox.Show("a is greater");
Seems safer :)
Convert them to integers and compare the integers.
There is also a simple algo based on String comparisson:
Assumed your numbers have a unique format: always lower case or higher case letters. Leading 0x or not, no leading zeros. Then you can do like this:
If number a has more digits than number b: a > b
If the number of digits is equal you could use String.Compare.
This algo has the advantage it is not limited to 32 or 64 bits.
Here is a fairly robust implementation of hendrik’s suggestion. There are a number of ways it could be optimized if your input strings have known attributes, but it should be able to compare valid hex strings of any size and/or with mixed formats.
public int HexStringCompare(string value1, string value2)
{
string InvalidHexExp = #"[^\dabcdef]";
string HexPaddingExp = #"^(0x)?0*";
//Remove whitespace, "0x" prefix if present, and leading zeros.
//Also make all characters lower case.
string Value1 = Regex.Replace(value1.Trim().ToLower(), HexPaddingExp, "");
string Value2 = Regex.Replace(value2.Trim().ToLower(), HexPaddingExp, "");
//validate that values contain only hex characters
if (Regex.IsMatch(Value1, InvalidHexExp))
{
throw new ArgumentOutOfRangeException("Value1 is not a hex string");
}
if (Regex.IsMatch(Value2, InvalidHexExp))
{
throw new ArgumentOutOfRangeException("Value2 is not a hex string");
}
int Result = Value1.Length.CompareTo(Value2.Length);
if (Result == 0)
{
Result = Value1.CompareTo(Value2);
}
return Result;
}
Using this to answer the OP's question:
if (HexStringCompare(a, b) > 0)
MessageBox.Show("a is greater");

easy and fast way to convert an int to binary?

What I am looking for is something like PHPs decbin function in C#. That function converts decimals to its representation as a string.
For example, when using decbin(21) it returns 10101 as result.
I found this function which basically does what I want, but maybe there is a better / faster way?
var result = Convert.ToString(number, 2);
– Almost the only use for the (otherwise useless) Convert class.
Most ways will be better and faster than the function that you found. It's not a very good example on how to do the conversion.
The built in method Convert.ToString(num, base) is an obvious choice, but you can easily write a replacement if you need it to work differently.
This is a simple method where you can specify the length of the binary number:
public static string ToBin(int value, int len) {
return (len > 1 ? ToBin(value >> 1, len - 1) : null) + "01"[value & 1];
}
It uses recursion, the first part (before the +) calls itself to create the binary representation of the number except for the last digit, and the second part takes care of the last digit.
Example:
Console.WriteLine(ToBin(42, 8));
Output:
00101010
int toBase = 2;
string binary = Convert.ToString(21, toBase); // "10101"
To have the binary value in (at least) a specified number of digits, padded with zeroes:
string bin = Convert.ToString(1234, 2).PadLeft(16, '0');
The Convert.ToString does the conversion to a binary string.
The PadLeft adds zeroes to fill it up to 16 digits.
This is my answer:
static bool[] Dec2Bin(int value)
{
if (value == 0) return new[] { false };
var n = (int)(Math.Log(value) / Math.Log(2));
var a = new bool[n + 1];
for (var i = n; i >= 0; i--)
{
n = (int)Math.Pow(2, i);
if (n > value) continue;
a[i] = true;
value -= n;
}
Array.Reverse(a);
return a;
}
Using Pow instead of modulo and divide so i think it's faster way.

How can I Convert a Big decimal number to Hex in C# (Eg : 588063595292424954445828)

The number is bigger than int & long but can be accomodated in Decimal. But the normal ToString or Convert methods don't work on Decimal.
I believe this will produce the right results where it returns anything, but may reject valid integers. I dare say that can be worked around with a bit of effort though... (Oh, and it will also fail for negative numbers at the moment.)
static string ConvertToHex(decimal d)
{
int[] bits = decimal.GetBits(d);
if (bits[3] != 0) // Sign and exponent
{
throw new ArgumentException();
}
return string.Format("{0:x8}{1:x8}{2:x8}",
(uint)bits[2], (uint)bits[1], (uint)bits[0]);
}
Do it manually!
http://www.permadi.com/tutorial/numDecToHex/
I've got to agree with James - do it manually - but don't use base-16. Use base 2^32, and print 8 hex digits at a time.
I guess one option would be to keep taking chunks off it, and converting individual chunks? A bit of mod/division etc, converting individual fragments...
So: what hex value do you expect?
Here's two approaches... one uses the binary structure of decimal; one does it manually. In reality, you might want to have a test: if bits[3] is zero, do it the quick way, otherwise do it manually.
decimal d = 588063595292424954445828M;
int[] bits = decimal.GetBits(d);
if (bits[3] != 0) throw new InvalidOperationException("Only +ve integers supported!");
string s = Convert.ToString(bits[2], 16).PadLeft(8,'0') // high
+ Convert.ToString(bits[1], 16).PadLeft(8, '0') // middle
+ Convert.ToString(bits[0], 16).PadLeft(8, '0'); // low
Console.WriteLine(s);
/* or Jon's much tidier: string.Format("{0:x8}{1:x8}{2:x8}",
(uint)bits[2], (uint)bits[1], (uint)bits[0]); */
const decimal chunk = (decimal)(1 << 16);
StringBuilder sb = new StringBuilder();
while (d > 0)
{
int fragment = (int) (d % chunk);
sb.Insert(0, Convert.ToString(fragment, 16).PadLeft(4, '0'));
d -= fragment;
d /= chunk;
}
Console.WriteLine(sb);

Categories