开发者

byte[] to unsigned BigInteger?

开发者 https://www.devze.com 2023-02-25 02:08 出处:网络
Motivation: I would like to convert hashes (MD5/SHA1 etc) into decimal integers for the purpose of making barcodes in Code128C.

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[开发者_Go百科] 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号