Parsing a large exponential number in .NET - c#

I am trying to convert some Java code into C# and ran across an issue with parsing very large exponential numbers in .NET.
The number I am trying to parse is "1.79769313486232E+308".
I have tried using both double (which is what is used in the code I am translating) and decimal, but both throw an overflow exception that the number is too large.
double result = double.Parse("1.79769313486232E+308",
System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture)
I have tried various other combinations as well, such as using NumberStyles.Any.
This is working fine in Java. But before I attempt to convert the code from Java, I was hoping that there is another (native) option in .NET. Any ideas?

System.Numerics.BigInteger result = System.Numerics.BigInteger.Parse("1.79769313486232E+308", System.Globalization.NumberStyles.Float);
You can try BigInteger you should add reference to System.Numerics in your project
EDIT
Because of the comments, current number can be represented by int(without losing any information) because it is integer itself. This is scientific notation so how this translates. For an example:
1.23E+11 or as 1.23 X 10^11
So in his case:
1.79769313486232E+308 = 1.79769313486232*10^308
Which is away from double boundaries and can be written as biginteger. The number is integer itself so there is no problem!

Because it is too large bro.
Double can hold up to:
1.7976931348623157E+308
See: this

Related

Difference between binary to float conversion in C# and C/C++

When converting a binary number in C/C++ and C# we're getting 2 different results by its rounding.
For example - let's take 1000010000010110110000010111111, in C# - we would get 34.84448 while we would get 34.844479, why is this minor difference?
Converting in C#:
float f = System.BitConverter.ToSingle(bytearray,0);
//bytearray is an array that contains our binary number
in C++:
int a = 1108041919; //The number that is being represented
float f = *(float *)&a;
There are many ways to unambiguously represent the same floating point value in decimal. For example, you can add arbitrarily many zeros after the exact output (note that since each power of two has a decimal representation of finite length, so does every floating point number).
The criterion for "when can I stop printing extra digits" is usually chosen as "you can stop printing extra digits when you would get the exact same value back if you parsed the decimal output into a float again". In short: It is expected that outputting a float "round-trips".
If you parse the decimal representations 34.844479 and 34.84448, you will find that they both convert back to the floating point value 0x420b60bf or 01000010000010110110000010111111. So both these strings represent the same floating point number. (Source: Try it yourself on https://www.h-schmidt.net/FloatConverter/IEEE754.html)
Your question boils down to "Why do the different runtime libraries print out different values for the same float?", to which the answer is "it's generally up to the library to figure out when to stop printing digits, they are not required to stop at the bare minimum". As long as you can get the same float back when you parse it again, the library did its job.
If you want to see the exact same decimal strings, you can achieve that with appropriate formatting options.
Since the value is the same we could guess that the printing function that is handling the value could be the minor difference in there :-)

Convert binary 32bit IEEE-754 floating points to Double in .net

I'm trying to parse a binary STereoLithography file(.stl) in .net(C#) which has 32-bit floating-point numbers(IEEE-754) in it.
I need to parse those numbers and then later store those numbers in a string representation in a PovRay script, which is a plain text file.
I tried this in nodejs using the readFloatLE function which gives me back a Number(double-precision value).
In .net I only found the Bitconverter.ToSingle function which reads the binary 32bits and gives me a float which has less decimal precision(7) than the nodejs parsing.
The nodejs parsing gives a povray-script with nubmers like: -14.203535079956055
While the .net only gives me: -14.2035351
So, how do I parse the binary 32 bits to a Double in .net to get the higher precision?
[Edit]
Using the anwser from taffer: casting to converted float to a double and then using the 'round-trip' formatter for string representation.
Comparing to the nodejs output there are still minor rounding differences but those are in the 13th-16th decimals.
You did not lose any precision. Unlike JavaScript, the default .NET ToString uses general number formatting, which may truncate the last digits.
But if you use the round-trip format specifier you get the exact result:
var d = double.Parse("-14.203535079956055");
Console.WriteLine(d.ToString("R")); // displays -14.203535079956055
Edit
In JavaScript there is no 32-bit floating number type. Every number is a double. So even if you use the readFloatLE function, it will be parsed as a double from 32 bits. See the C# code below, which demonstrates what actually happens:
var d = (double)float.Parse("-14.2035351");
Console.WriteLine(d.ToString("R")); // displays -14.203535079956055
Or even more precisely if you read the numbers from a byte buffer:
var d = (double)BitConverter.ToSingle(new byte[] { 174,65,99,193 }, 0);
Console.WriteLine(d.ToString("R")); // displays -14.203535079956055

Math-pow incorrect results

double a1;
a1 = Math.Pow(somehighnumber, 40);
something.Text = Convert.ToString(xyz);
the result i get is have E+41 etc.
its like 1,125123E+41 etc. i dont get why.
Your question is very unclear; in the future, you'll probably get better results if you post a clear question with a code sample that actually compiles and demonstrates the problem you're actually having. Don't make people guess what the problem is.
If what you want to do is display a double-precision floating point number without the scientific notation then use the standard number formatting specifier:
Console.WriteLine(string.Format("{0:N}", Math.Pow(10, 100)));
Results in:
10,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000.00
If what you have a problem with is that the result is rounded off, then don't use double-precision floats; they are accurate to only 15 decimal places. Try doing your arithmetic in BigIntegers, which have arbitrary integer precision.
That's scientific notation. It means 1.125123 * 1041. Scientific notation is useful if your number becomes so large that displaying it in full would require a lot of screen space. Also, floating point arithmetic is not precise so even if you did display the number in full most of the digits would be incorrect anyway.
If you want precise calculations you should use BigInteger instead of double (this type is present in .NET 4.0 or newer).
double bigNum = Math.Pow(100, 100);
string bigString = string.Format("{0:F}", bigNum);
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx#FFormatString
Or you can use the 4.0 indroduced BigInteger(add a reference to System.Numerics to the Project):
Numerics.BigInteger bigInt = Numerics.BigInteger.Pow(1000, 1000);
string veryBigString = bigInt.ToString("F");
As you can see it also works with ToString.

How do you deal with numbers larger than UInt64 (C#)

In C#, how can one store and calculate with numbers that significantly exceed UInt64's max value (18,446,744,073,709,551,615)?
Can you use the .NET 4.0 beta? If so, you can use BigInteger.
Otherwise, if you're sticking within 28 digits, you can use decimal - but be aware that obviously that's going to perform decimal arithmetic, so you may need to round at various places to compensate.
By using a BigInteger class; there's one in the the J# libraries (definitely accessible from C#), another in F# (need to test this one), and there are freestanding implementations such as this one in pure C#.
What is it that you wish to use these numbers for? If you are doing calculations with really big numbers, do you still need the accuracy down to the last digit?
If not, you should consider using floating point values instead. They can be huge, the max value for the double type is 1.79769313486231570E+308, (in case you are not used to scientific notation it means 1.79769313486231570 multiplied by 10000000...0000 - 308 zeros).
That should be large enough for most applications
BigInteger represents an arbitrarily large signed integer.
using System.Numerics;
var a = BigInteger.Parse("91389681247993671255432112000000");
var b = new BigInteger(1790322312);
var c = a * b;
Decimal has greater range.
There is support for bigInteger in .NET 4.0 but that is still not out of beta.
There are several libraries for computing with big integers, most of the cryptography libraries also offer a class for that. See this for a free library.
Also, do check that you truly need a variable with greater capacity than Int64 and aren't falling foul of C#'s integer arithmetic.
For example, this code will yield an overflow error:
Int64 myAnswer = 20000*1024*1024;
At first glance that might seem to be because the result is too large for an Int64 variable, but actually it's because each of the numbers on the right side of the formula are implicitly typed as Int32 so the temporary memory space reserved for the result of the calculation will be Int32 size, and that's what causes the overflow.
The result will actually easily fit into an Int64, it just needs one of the values on the right to be cast to Int64:
Int64 myAnswer = (Int64)20000*1024*1024;
This is discussed in more detail in this answer.
(I appreciate this doesn't apply in the OP's case, but it was just this sort of issue that brought me here!)
You can use decimal. It is greater than Int64.
It has 28-29 significant digits.

Get the decimal part of a number and the number of places after the decimal point (C#)

Does anyone know of an elegant way to get the decimal part of a number only? In particular I am looking to get the exact number of places after the decimal point so that the number can be formatted appropriately. I was wondering if there is away to do this without any kind of string extraction using the culture specific decimal separator....
For example
98.0 would be formatted as 98
98.20 would be formatted as 98.2
98.2765 would be formatted as 98.2765 etc.
It it's only for formatting purposes, just calling ToString will do the trick, I guess?
double d = (double)5 / 4;
Console.WriteLine(d.ToString()); // prints 1.75
d = (double)7 / 2;
Console.WriteLine(d.ToString()); // prints 3.5
d = 7;
Console.WriteLine(d.ToString()); // prints 7
That will, of course, format the number according to the current culture (meaning that the decimal sign, thousand separators and such will vary).
Update
As Clement H points out in the comments; if we are dealing with great numbers, at some point d.ToString() will return a string with scientific formatting instead (such as "1E+16" instead of "10000000000000000"). One way to overcome this probem, and force the full number to be printed, is to use d.ToString("0.#"), which will also result in the same output for lower numbers as the code sample above produces.
You can get all of the relevant information from the Decimal.GetBits method assuming you really mean System.Decimal. (If you're talking about decimal formatting of a float/double, please clarify the question.)
Basically GetBits will return you 4 integers in an array.
You can use the scaling factor (the fourth integer, after masking out the sign) to indicate the number of decimal places, but you should be aware that it's not necessarily the number of significant decimal places. In particular, the decimal representations of 1 and 1.0 are different (the former is 1/1, the latter is 10/10).
Unfortunately, manipulating the 96 bit integer is going to require some fiddly arithmetic unless you can use .NET 4.0 and BigInteger.
To be honest, you'll get a simpler solution by using the built in formatting with CultureInfo.InvariantCulture and then finding everything to the right of "."
Just to expand on the point about getbits, this expression gets the scaling factor from a decimal called foo:
(decimal.GetBits(foo)[3] & 16711680)>>16
You could use the Int() function to get the whole number component, then subtract from the original.

Categories