High
High

Reputation: 626

C# Convert big decimal numbers to byte array

How can I convert a big decimal integer to a byte array.

var number = "969837669069837851043825067021609343597253227631794160042862620526559";

Note that I can't use BigInteger because I'm using Unity under .NET 3.5.

Upvotes: 0

Views: 1329

Answers (2)

Christopher
Christopher

Reputation: 9824

You can write your own "BigInteger like type" but I would highly advise against it. It is one of those things were you can do a lot of stuff very wrong very quickly. And you will never even approach the efficiency of a builtin type like BigInteger.

I did write a TryParse replacement for someone stuck on 1.0 however, so I might be able to give you some hints:

  • use a list of UnsignedIntegers. Use the biggest integer avalible as the basic type, that way the indexes will stay sanely small. And a list because you do not want to deal with growth/shrinking of the integer too
  • Change into checked context when doing math on any two elements. The .NET Framework can fully detect overflow an underflow errors, but that detection is turned off by default. If you got a overflow or underflow error, that means you should increase/decrease the next digit accordingly
  • most arythmethic requires at least one temporary variable. For addition and substraction, you need to store the overflow/underflow cases. For Multiplication you need to multiply every array element of ListA with every array Element of ListB. You just multiply each value ListA with one Element of ListB. Put it into some temporary variable. Then add it to the running sum.
  • This article on equality/identity checks might help you doing that part right: http://www.codeproject.com/Articles/18714/Comparing-Values-for-Equality-in-NET-Identity-and You want the value type Semantics.
  • Ideally you want to make this type inmutable. Most integrated types and string are (including BigInteger), just so it is easier to work with them in Multitasking/threading scenarios.
  • You may have to do parsing and toString(). If so, culture appropirate formating may become a issue quickly. Most numerical types have Parse() and toString() function that accepts a CultureNumberFormat as parameter. The default overloads simply retreive the thread culture/some other default and use hand it of to their brother.

As for the TryParse, here is what I wrote for that case way back:

//Parse throws ArgumentNull, Format and Overflow Exceptions.
//And they only have Exception as base class in common, but identical handling code (output = 0 and return false).

bool TryParse(string input, out int output){
  try{
    output = int.Parse(input);
  }
  catch (Exception ex){
    if(ex is ArgumentNullException ||
      ex is FormatException ||
      ex is OverflowException){
      //these are the exceptions I am looking for. I will do my thing.
      output = 0;
      return false;
    }
    else{
      //Not the exceptions I expect. Best to just let them go on their way.
      throw;
    }
  }

  //I am pretty sure the Exception replaces the return value in exception case. 
  //So this one will only be returned without any Exceptions, expected or unexpected
  return true;

}

Upvotes: 1

Douglas Dwyer
Douglas Dwyer

Reputation: 612

I, personally, would use BigInteger. You can change Unity's scripting equivalent to .NET 4.6 under the player settings, which will give you access to a whole bunch of frameworks previously inaccessible. According to the documentation .NET 4.6 should contain BigInteger, thus solving your issue.

To change the scripting equivalent, go to Build Settings => Player Settings => Other Settings => Configuration. In that list of settings, you should be able to set the script runtime equivalent.

Once you've done that, all you have to do convert the number:

var number = "969837669069837851043825067021609343597253227631794160042862620526559";
byte[] numberBytes = BigInteger.Parse(number).ToByteArray();

Upvotes: 2

Related Questions