Motivation:
I would like to convert hashes (MD5/SHA1 etc) into decimal integers for the purpose of making barcodes in Code128C.
For simplicity, I prefer all the resulting (large) numbers to be positive.
I am able to convert byte[] to BigInteger in C#...
Sample from what I have so far:
byte[] data;
byte[] result;
BigInteger biResult;
result = shaM.ComputeHash(data);
biResult = new BigInteger(result);
But (rusty CS here) am I correct that a byte array can always be interpreted in two ways:
(A): as a signed number
(B): as an unsigned number
Is it possible to make an UNSIGNED BigInteger from a byte[] in C#?
Should I simply prepend a 0x00 (zero byte) to the front of the byte[]?
EDIT:
Thank you to AakashM, Jon and Adam Robinson, appending a zero byte achieved what I needed.
EDIT2:
The main thing I should have done was to read the detailed doc of the BigInteger(byte[]) constructor, then I would have seen the sections about how to restrict to positive numbers by appending the zero byte.
The remarks for the BigInteger constructor state that you can make sure any BigInteger created from a byte[] is unsigned if you append a 00 byte to the end of the array before calling the constructor.
Note: the BigInteger constructor expects the array to be in little-endian order. Keep that in mind if you expect the resulting BigInteger to have a particular value.
Since .NET Core 2.1, BigInteger has a constructor with an optional parameter isUnsigned:
public BigInteger (ReadOnlySpan<byte> value, bool isUnsigned = false, bool isBigEndian = false);
Examining the documentation for the relevant BigInteger constructor, we see:
The individual bytes in the value
array should be in little-endian
order, from lowest-order byte to
highest-order byte
[...]
The constructor expects positive
values in the byte array to use
sign-and-magnitude representation, and
negative values to use two's
complement representation. In other
words, if the highest-order bit of the
highest-order byte in value is set,
the resulting BigInteger value is
negative. Depending on the source of
the byte array, this may cause a
positive value to be misinterpreted as
a negative value.
[...]
To prevent
positive values from being
misinterpreted as negative values, you
can add a zero-byte value to the end
of the array.
As other answers have pointed out, you should append a 00 byte to the end of the array to ensure the resulting BigInteger is positive.
According to the the BigInteger Structure (System.Numerics) MSDN Documentation
To prevent the BigInteger(Byte[]) constructor from confusing the two's complement representation of a negative value with the sign and magnitude representation of a positive value, positive values in which the most significant bit of the last byte in the byte array would ordinarily be set should include an additional byte whose value is 0.
Here's code to do it:
byte[] byteArray;
// ...
var bigInteger = new BigInteger(byteArray.Concat(new byte[] { 0 }).ToArray());
But (rusty CS here) am I correct that a byte array can always be interpreted in two ways: A: as a signed number B: as an unsigned number
What's more correct is that all numbers (by virtue of being stored in the computer) are basically a series of bytes, which is what a byte array is. It's not true to say that a byte array can always be interpreted as a signed or unsigned version of a particular numeric type, as not all numeric types have signed and unsigned versions. Floating point types generally only have signed versions (there's no udouble or ufloat), and, in this particular instance, there is no unsigned version of BigInteger.
So, in other words, no, it's not possible, but since BigInteger can represent an arbitrarily large integer value, you're not losing any range by virtue of its being signed.
As to your second question, you would need to append 0x00 to end end of the array, as the BigInteger constructor parses the values in little-endian byte order.
Related
What is the difference between byte and byte array?
byte[] array1 ={1,0,0,0}
Does this means that the array 1 is having byte value of 1000?
How can I differentiate when to use byte and byte array?
A byte is (in the case of c#) an unsigned integer composed of 8 bits, so: an integer in the range [0,255]; a byte[] is a fixed size chunk of byte values, in this case 4 values, with initial values (sequentially) one, zero, zero, zero. This is not the same as a value of 1000 - it is 4 discreet values. You could coerce a byte[] payload to an integer, but what value that means is ambiguous:
we could treat it as a raw big-endian 32-bit integer
we could treat it as a raw little-endian 32-bit integer
we could treat the 4 elements as decimal digits
we could treat the 4 elements as ASCII characters that might represent decimal digits
or the same with a non-ASCII encoding, for example UTF-16 (big or little endian), UTF-32, etc
etc
As for when to use each: are you talking about one value, or multiple values? note that byte[] is typically used when talking about binary payloads such as file/network contents, although you can use byte[] for more specific scenarios unrelated to this.
byte is a variable that will be between 0 and 255 . byte array is an array that contains byte values ( value 0 to 255)
An array is a structure containing multiple values of the same type. A byte array therefore contains multiple bytes. Your array four bytes. The first one is 1, second one 0, third one 0, and so on. The array does have a value of {1,0,0,0}, or [1,0,0,0], and when you call its ToString() method, you get "System.Byte[]".
In C#, byte is the data type for 8-bit unsigned integers, so a byte[] should be an array of integers who are between 0 and 255, just like an char[] is an array of characters.
But most of time when I encounter byte[], I see byte[] is used as a contiguous chunk of memory for storing raw representation of data.
How do these two relate to each other?
thanks
Well, a byte as datatype is exactly what you already said, an unsigned integer between 0 and 255. Furthermore this type needs exactly - believe it or not - one byte in your memory, thus also the name. This is why most readers that read byte per byte store those information in a structure that fits exactly the size of a byte - the byte-datatype.
I'm trying to convert a byte array into hexadecimal value using Bitconverter class.
long hexValue = 0X780B13436587;
byte[] byteArray = BitConverter.GetBytes ( hexValue );
string hexResult = BitConverter.ToString ( byteArray );
now if I execute the above code line by line, this is what I see
I thought hexResult string would be same as hexValue (i.e. 780B13436587h) but what I get is different, am I missing something, correct me if I'm wrong.
Thanks!
Endianness.
BitConverter uses CPU-endianness, which for most people means: little-endian. When humans write numbers, we tend to write big-endian (broadly speaking: you write the thousands, then hundreds, then tens, then the digits). For a CPU, big-endian means that the most-significant byte is first and the least-significant byte is last. However, unless you're using an Itanium, your CPU is probably little-endian, which means that the most-significant byte is last, and the least-significant byte is first. The CPU is implemented such that this doesn't matter unless you are peeking inside raw memory - it will ensure that numeric and binary arithmetic still works the way you expect. However, BitConverter works by peeking inside raw memory - hence you see the reversed data.
If you want the value in big-endian format, then you'll need to:
do it manually in big-endian order
check the BitConverter.IsLittleEndian value, and if true:
either reverse the input bytes
or reverse the output
If you look closely, the bytes in the output from BitConverter are reversed.
To get the hex-string for a number, you use the Convert class:
Convert.ToString(hexValue, 16);
It is the same number but reversed.
BitConverter.ToString can return string representation in reversed order:
http://msdn.microsoft.com/en-us/library/3a733s97(v=vs.110).aspx
"All the elements of value are converted. The order of hexadecimal strings returned by the ToString method depends on whether the computer architecture is little-endian or big-endian."
I have a need to convert an Int32 value to a 3-byte (24-bit) integer. Endianness remains the same (little), but I cannot figure out how to move the sign appropriately. The values are already constrained to the proper range, I just can't figure out how to convert 4 bytes to 3. Using C# 4.0. This is for hardware integration, so I have to have 24-bit values, cannot use 32 bit.
If you want to do that conversion, just remove the top byte of the four-byte number. Two's complement representation will take care of the sign correctly. If you want to keep the 24-bit number in an Int32 variable, you can use v & 0xFFFFFF to get just the lower 24 bits. I saw your comment about the byte array: if you have space in the array, write all four bytes of the number and just send the first three; that is specific to little-endian systems, though.
Found this: http://bytes.com/topic/c-sharp/answers/238589-int-byte
int myInt = 800;
byte[] myByteArray = System.BitConverter.GetBytes(myInt);
sounds like you just need to get the last 3 elements of the array.
EDIT:
as Jeremiah pointed out, you'd need to do something like
int myInt = 800;
byte[] myByteArray = System.BitConverter.GetBytes(myInt);
if (BitConverter.IsLittleEndian) {
// get the first 3 elements
} else {
// get the last 3 elements
}
I have a byte array represented by hex values, these are time durations. The data could be converted to integer values and multiplied by a constant to get the timings. The decoding of the data will be saved to a file as a series of hex strings. What would be an efficient way of manipulating hex values?
I was looking at performance issues when dealing with data formats, as I have to work with more than one format at different stages (calculations, data display, etc.). Most examples show the conversion from byte[] to hex string ("1A 3C D4"), and viceversa, but I was looking for an alternative, which is to convert to Int16 and use char[] array.
You don't have a byte array representing hex values. You have a byte array representing numbers. The base you represent a number in is only relevant when you're representing it.
To put it a different way: if you thought of your byte array as representing decimal integers instead, how do you imagine it would be different? Is my height different if I represent it in feet and inches instead of metres?
Now, if you're trying to represent 16-bit numbers, I'd suggest that using a byte array is a bad idea. Use a ushort[] or short[] instead, as those are 16-bit values. If you're having trouble getting the data into an array like that, please give details... likewise if you have any other problems with the manipulation. Just be aware that until you're writing the data out as text, there's really no such concept as which base it's in, as far as the computer is concerned.
(Note that this is different for floating point values, where the data really would be different between a decimal and a double, for example... there, the base of representation is part of the data format. It's not for integers. Alternatively, you can think of all integers as just being binary until you decide to format them as text...)
From MSDN:
The hexadecimal ("X") format specifier
converts a number to a string of
hexadecimal digits. The case of the
format specifier indicates whether to
use uppercase or lowercase characters
for hexadecimal digits that are
greater than 9. For example, use "X"
to produce "ABCDEF", and "x" to
produce "abcdef". This format is
supported only for integral types.
The precision specifier indicates the
minimum number of digits desired in
the resulting string. If required, the
number is padded with zeros to its
left to produce the number of digits
given by the precision specifier.
byte x = 60;
string hex = String.Format("0x{0:X4}", x);
Console.WriteLine(hex); // prints "0x003C"