so I just started experimenting with C#. I have one line of code and the output is a "?".
Code: Console.WriteLine(Math.Pow(Math.Exp(1200), 0.005d));
Output: ?
I am using Visual Studio and it also says exited with code 0.
It should output 403.4287934927351. I also tried it out with Geogebra and it's correct as shown in the image so it's not infinity.
C# double type (which is returned by Math.Exp function) is a fixed-size type (64 bits), and so it cannot represent arbitrary large numbers. Largest number it can represent is double.MaxValue constant, and it's of order 10^308, which is less than what you are trying to compute (e^2000).
When result of computation exceeds maximum representable value - special "number" representing Infinity is returned. So
double x = Math.Exp(1200); // cannot represent this with double type
bool isInifinite = double.IsInfinity(x); // true
After you got this "infinity" - all other computations involving it will just return infinity back, there is nothing else they can do. So then whole expression Math.Pow(Math.Exp(1200), 0.005d)) returns "infinity".
When you try to write result to console, it gets converted to string. The rules for converting mentioned infinity to string are as follows:
Regardless of the format string, if the value of a Single or Double
floating-point type is positive infinity, negative infinity, or not a
number (NaN), the formatted string is the value of the respective
PositiveInfinitySymbol, NegativeInfinitySymbol, or NaNSymbol property
that is specified by the currently applicable NumberFormatInfo object.
In your current culture, PositiveInfinitySymbol is likely "∞", but your console encoding likely cannot represent this symbol, so it outputs "?". You can change console encoding to UTF8 like this:
Console.OutputEncoding = Encoding.UTF8;
And then it will show "∞" correctly.
There is no framework-provided type to work with arbitrary sized rational numbers, as far as I know. For integer there is BigInteger type though.
In this specific case you can do fine with just double, because you can do the same thing with:
Console.WriteLine(Math.Exp(1200 * 0.005d));
// outputs 403.4287934927351
Now there are no intermediate results exceeding capacity of double, and so it works fine.
For cases where it's not possible - there are third party libraries which allow to work with arbitrary large rationals.
Related
According to microsoft documentation the [BigInt] datatype seems to have no defined maximum value and theoretically can hold an infinitely large number, but I found that after the 28th digit, some weird things start to occur:
PS C:\Users\Neko> [BigInt]9999999999999999999999999999
9999999999999999999999999999
PS C:\Users\Neko> [BigInt]99999999999999999999999999999
99999999999999991433150857216
As you can see, on the first command1, the BigInt works as intended, but with one more digit, some falloff seems to occur where it translates 99999999999999999999999999999 to 99999999999999991433150857216 however, the prompt throws no error and you can continue to add more digits until the 310th digit
PS C:\Users\Neko> [BigInt]99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
100000000000000001097906362944045541740492309677311846336810682903157585404911491537163328978494688899061249669721172515611590283743140088328307009198146046031271664502933027185697489699588559043338384466165001178426897626212945177628091195786707458122783970171784415105291802893207873272974885715430223118336
PS C:\Users\Neko\> [BigInt]999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
which will throw the error
At line:1 char:318
+ ... 999999999999999999999999999999999999999999999999999999999999999999999
+ ~
The numeric constant 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 is not valid.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : BadNumericConstant
Which I believe is a console issue rather than a BigInt issue because the error doesn't mention the [BigInt] datatype unlike numbers too big for other datatypes like
PS C:\Users\Neko> [UInt64]18446744073709551615
18446744073709551615
PS C:\Users\Neko> [UInt64]18446744073709551616
Cannot convert value "18446744073709551616" to type "System.UInt64". Error: "Value was either too large or too small
for a UInt64."
At line:1 char:1
+ [UInt64]18446744073709551616
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastIConvertible
As for C#, System.Numerics.BigInt will start throwing an error at the 20th digit, 99999999999999999999 when hard coded:
namespace Test
{
class Test
{
static void Main()
{
System.Numerics.BigInteger TestInput;
System.Numerics.BigInteger Test = 99999999999999999999;
System.Console.WriteLine(Test);
}
}
}
When trying to build in Visual Studio I get the error
Integral constant is too large
However, I can enter a bigger number to ReadLine without causing an error
namespace Test
{
class Test
{
static void Main()
{
System.Numerics.BigInteger TestInput;
TestInput = System.Numerics.BigInteger.Parse(System.Console.ReadLine());
System.Console.WriteLine(TestInput);
}
}
}
Which seems to indeed be infinite. The input
99999999999...
(24720 characters total) works fine2
So what is causing all of this weird activity with [BigInt]?
1 which is 28 digits according to ([Char[]]"$([BigInt]9999999999999999999999999999)").count
2 I am too lazy to count the digits and trying to parse the digits into PowerShell causes an error. According to this it is 24720 characters
TLDR: Use [BigInt]::Parse or 'literal' syntax prior to Powershell Core 7.0; otherwise use the n suffix.
The Problem - double literals
When it comes to un-suffixed literals, Powershell will use the first type the value fits in. The order for integral literals is int, long, decimal and then double. From the documentation for Powershell 5.1 (bolding mine; this paragraph is the same for Powershell Core):
For an integer literal with no type suffix:
If the value can be represented by type [int], that is its type.
Otherwise, if the value can be represented by type [long], that is its type.
Otherwise, if the value can be represented by type [decimal], that is its type.
Otherwise, it is represented by type [double].
In your case the value exceeds that of decimal.MaxValue so your literal is by default a double literal. That double value is not exactly representable and is "converted" to the closest representable double.
$h = [double]99999999999999999999999999999
"{0:G29}" -f $h
Outputs
99999999999999991000000000000
Obviously that's not the exact number, just a representation in string form. But it gives you an idea what's going on. Now we take this inexact double value and we cast it to BigInt. The original loss in precision is transferred over and compounded upon by the conversion operator. This is what is actually happening in Powershell (note the cast to BigInt):
$h = [BigInt][double]99999999999999999999999999999
"{0:G}" -f $h
Outputs
99999999999999991433150857216
This is in fact the closest representable double value. If you could print the exact value of the double from the first example, this is what it would print. When you add the additional extra digits, you exceed the largest value of a numeric literal, thus the other exception you received.
C# Inconsistencies
Unlike Powershell, C# uses integral literals by default which is why you get the exception for a lot fewer digits. Adding the D suffix in C# will give you a larger range. The following works fine and will be a double.
var h = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999D;
Adding one more digit will raise the following error:
error CS0594: Floating-point constant is outside the range of type 'double'
Note that in Powershell the D suffix is used for decimal literals and not double. There is not an explicit suffix for double--it is assumed to be the default.
Solutions
Back to your original problem, depending on your Powershell version the solution may vary:
[BigInt]::Parse
If you are using Windows Powershell or Powershell Core <= v6.2, one option is to use BigInteger.Parse:
[bigint]::Parse("99999999999999999999999999999")
Outputs:
99999999999999999999999999999
Large Value Literals
As pointed out in the comments, another option that works is to enclose the literal in quotes.
[bigint]'99999999999999999999999999999'
Outputs
99999999999999999999999999999
Despite how it looks, this is not shorthand for [bigint]::new([string]) (see below). This is instead a way to ensure that the literal is not treated as a double but rather as an integral literal with many digits, a so-called "large value literal". See this section of the docs.
N Integral Suffix (v7.0+)
Powershell Core 6.2 introduced many new literal suffixes for integral types such as unsigned, short, and byte but did not introduce one for bigint. That came along in Powershell Core 7.0 via the n suffix. This means you can now do the following:
99999999999999999999999999999n
Outputs:
99999999999999999999999999999
See the documentation for more information on the suffixes available in Powershell Core.
[BigInt]::new
If you were to try [bigint]::new('literal') Powershell recognizes that you intend to use the value as a literal. There is in fact no constructor for BigInt that accepts a string (we use Parse for that) nor is there a constructor which accepts another BigInt. There is however a constructor that takes a double. Our large-value literal will start as a BigInt, Powershell will then implicitly convert that to a double (losing precision) and then pass it to [bigint]::new([double]) as the best match, once again giving an incorrect result:
[bigint]::new('99999999999999999999999999999')
Outputs:
99999999999999991433150857216
Unfortunately C# have not literal for BigInteger. There are two ways to instantiate BigInteger:
Convert from primitive type like int, long (cast or using constructor)
Parse from string using BigInteger.Parse
BigInteger test = BigInteger.Parse("32439845934875938475398457938457389475983475893475389457839475");
Console.WriteLine(test.ToString());
// output: 32439845934875938475398457938457389475983475893475389457839475
See How PowerShell parses numeric literals
To complement the existing, helpful answers - notably pinkfloydx33's - with a succinct summary:
By default, all PowerShell versions up to at least v7.0 use [double] as the data type for number literals that are larger than [decimal]::MaxValue, which invariably leads to a loss of accuracy.
Up to v6.x (which includes Windows PowerShell), the only way to avoid this is to use [bigint]::Parse() with the number represented as a string:
[bigint]::Parse('99999999999999999999999999999')
# A *cast* works too, as also shown in pinkfloydx33's answer:
[bigint] '99999999999999999999999999999'
In v7+, you can use the n suffix to designate a number literal as a [bigint]:
99999999999999999999999999999n # v7+; parses as a [bigint], due to suffix 'n'
Note: Arguably, given that PowerShell usually automatically picks an appropriate number type, it should assume n in this case, i.e. it should parse unsuffixed 99999999999999999999999999999 as a [bigint], not as a [double] - see this GitHub proposal.
Further reading:
See about_Numeric_Literals, which shows all number-type suffixes, including what PowerShell version they were introduced in.
This answer summarizes how number literals are interpreted in PowerShell.
In short: For integer literals, [int] is the smallest type ever chosen, with [long] or [decimal] chosen as needed to accommodate larger values, with [double] used for values beyond [decimal]::MaxValue.
A little more information coming at this from a metadata perspective,
PowerShell and C# will both use the same module in .NET Core to get the BigInt datatype, and you can view the metadata for the BigInteger struct in
C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Runtime.Numerics.dll
This includes the constructors for
public BigInteger(byte[] value);
public BigInteger(decimal value);
public BigInteger(double value);
public BigInteger(int value);
public BigInteger(long value);
public BigInteger(float value);
public BigInteger(uint value);
public BigInteger(ulong value);
public BigInteger(ReadOnlySpan<byte> value, bool isUnsigned = false, bool isBigEndian = false);
Which means the base
System.Numerics.BigInteger test = 12345;
Will inadvertently attempt to convert the value passed to the constructor into one of these datatypes which the highest value it could take, the maximum value of double, however C# will not try to convert a number to double unless specified with the D suffix so the max value that doesn't need a suffix would be ULong which has the max value of 18446744073709551615 (According to ULong.MaxValue) which happens to be less than 99999999999999999999, the number that caused the integral constant error, but greater than 9999999999999999999, one character less. This is why simply doing
System.Numerics.BigInteger test = 99999999999999999999;
will have an error. However, the Parse() method in BigInteger can take values other than the integer types from the constructor, it take strings:
public static BigInteger Parse(ReadOnlySpan<char> value, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null);
public static BigInteger Parse(string value);
public static BigInteger Parse(string value, NumberStyles style);
public static BigInteger Parse(string value, NumberStyles style, IFormatProvider provider);
public static BigInteger Parse(string value, IFormatProvider provider);
As you can see, the Parse() method for System.Numerics.BigInteger will take string arguments which have no limits since they aren't integers but words. This is why the Parse() method indeed will give you unlimited value space.
As for PowerShell, like in other answers say, anything past the [decimal] max value will attempt to get converted to the [double] datatype which has many inaccuracies and the [double] datatype's max value is 309 digits and that is why errors only show up after the 309th digit.
[double]::MaxValue
1.79769313486232E+308
To convert this to normal value not in scientific notation, we will move the decimal point over 308 times resulting in about
179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
being the highest possible double. The `[double] datatype in PowerShell also has very strange properties that are also very inaccurate like
[BigInt][double]9999999999999999999999
10000000000000000000000
[BigInt][double]9999999999999999999999999
10000000000000000905969664
[double]9999999999999999999
1E+19
Since PowerShell gets the BigInt type also from the same struct as C#, the methods and constructors are the same and Parse() will also work the same way in PowerShell as it does in C#. There were changes in PowerShell 7 allowing the N suffix to automatically be converted directly to BigInt.
BigInt also doesn't use scientific notation so it always will get the exact value if another datatype in used so to to get the exact value you could use
[BigInt]([double]::MaxValue)
Which will get you
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
being the highest possible double.
Commands that you want
PowerShell 6.x and below
[BigInt]::Parse("99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999")
PowerShell 7.0 and above
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999N
C#
System.Numerics.Biginteger test = System.Numerics.BigInteger.Parse("999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999")
How to convert hexadecimal string to number in C#?
I tried as below but it is giving negative value:
var dec1 = long.Parse("F0A6AFE69D2271E7", System.Globalization.NumberStyles.HexNumber);
// Result: dec1 = -1106003253459258905
While in Javascript it works fine as below:
var dec2 = parseInt("F0A6AFE69D2271E7", 16);
// Result: dec2 = 17340740820250292000
The number you're parsing is outside the range of long - long.MaxValue is 0x7FFFFFFFFFFFFFFF, and your value is 0xF0A6AFE69D2271E7.
Use ulong.Parse instead and it should be fine.
I suspect it's "working" in JavaScript because (at the time of writing) all JavaScript numbers are 64-bit floating point values, so have a huge range - but less precision, which is why a value which is clearly odd (last hex digit 7) is giving an even result.
See https://en.wikipedia.org/wiki/Two%27s_complement to understand why your number was interpreted as negative number. Presicely speaking, it's not "out of range" problem but, just your hex representation gives exact negative number. "long" type is signed integer and cannot hold full-64bit positive number since its MSB is kept for presenting negative numbers. Try using "ulong" instead.
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 :-)
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
I discovered this odd behavior. Then I tried a few experiments on the Immediate window of Visual Studio...
? Convert.ToSingle(Decimal.MinValue)
-7.92281625E+28
No surprises here.
? Convert.ToDecimal(Convert.ToSingle(Decimal.MinValue))
'Convert.ToDecimal(Convert.ToSingle(Decimal.MinValue))' threw an exception of type 'System.OverflowException'
base: {"Value was either too large or too small for a Decimal."}
First odd behavior: even if Decimal.MinValue is at the boundary of the Decimal domain, I thought that converting it to float wouldn't push it over the domain limit.
? Convert.ToDecimal(-7.92281625E+28)
-79228162500000000000000000000
Uhm... weird... oh not so weird: it is considering the expression as a double.
? Convert.ToDecimal(-7.92281625E+28F)
'Convert.ToDecimal(-7.92281625E+28F)' threw an exception of type 'System.OverflowException'
base: {"Value was either too large or too small for a Decimal."}
Let's try this....
? Convert.ToDecimal(-7.92281625E+28D)
-79228162500000000000000000000
... okay. As I thought, it can't convert that number if it is considering it a float, but it has no problem in converting it back to decimal when considering it a double.
? Convert.ToDecimal(Convert.ToDouble(Decimal.MinValue))
'Convert.ToDecimal(Convert.ToDouble(Decimal.MinValue))' threw an exception of type 'System.OverflowException'
base: {"Value was either too large or too small for a Decimal."}
Wait! What!?
Now I'm really lost. What's the difference between the last two expressions? And why does it fail to convert back from float?
You can check how exactly your value is represented within double variable using code posted by Eric Lipper on his blog: Looking inside a double
For your Convert.ToDouble(decimal.MinValue) it prints following info:
Raw sign: 1
Raw exponent: 10001011111
Raw mantissa: 0000000000000000000000000000000000000000000000000000
Normal
Sign: -
Exponent: 96
Exact binary fraction: 1.0000000000000000000000000000000000000000000000000000
Nearest approximate decimal: -7,92281625142643E+28
Exact rational fraction: -79228162514264337593543950336
Exact decimal fraction: -79228162514264337593543950336
Exact decimal fraction is the most important part here.
exact decimal fraction: -79,228,162,514,264,337,593,543,950,336
decimal.MinValue: -79,228,162,514,264,337,593,543,950,335
As you can see, it's slightly lower than decimal.MinValue, and that's why you're getting an exception.
The same case applies to Convert.ToSingle(Convert.ToSingle(decimal.MinValue)).
The types Single and Double doesn't represent all values exactly, like the Decimal type does.
The Double literal -7.92281625E+28 doesn't end up as a Double that contains that value exactly, only the closest value that can be represented by that type. Most literal values are adjusted slightly upwards or downwards, as the storage in the floating point types are based on binary numbers, not decimal numbers.
When you convert Decimal.MinValue to a Single, it will be adjusted slightly downwards, which means that it gets just out of the range that can be represented by a Decimal. When you try to convert it back to Decimal that will fail, because it's out of range. The conversion only works if the number is within the range of a Decimal, not when it is within the range that a Decimal can be converted to.
The double representation of Decimal.MinValue is not exact and is a bit smaller than Decimal.MinValue causing the overflow.
VS 2012 Immediate window gives the following results which indicate this a little better.
?Decimal.MinValue
-79228162514264337593543950335
?Convert.ToDouble(Decimal.MinValue)
-7.9228162514264338E+28
Convert.ToDouble is...
-79228162514264338000000000000
Notice the last digit is an 8 vs 7 in Decimal.MinValue which makes it too small to fit into a Decimal.