2010-05-28 47 views
4

我有等于1.212E + 25C# - 递增双值(1.212E + 25)

当我把它扔出去,以文字我myVar.ToString( “0000000000000000000000”)

双重价值

问题是即使我做myVar ++ 3或4次的值似乎保持不变。

这是为什么?

回答

1

doubleDouble)持有约16的精度数字和longInt64)AB出18位数字。

这些都没有足够的精度满足您的需求。

但是decimalDecimal)最多可容纳30位精度。虽然这似乎足够满足您的需求,但我建议您谨慎以防万一您的需求变得更大。在这种情况下,您可能需要第三方数字库。

相关的StackOverflow条目:
How can I represent a very large integer in .NET?
Big integers in C#

3

这是因为双精度是不够的。它根本无法保存很多有效数字。

它不适合长时间,但可能成为一个十进制。

不过...你真的需要这个级别的精确度?

+0

使其成为一个长会做到这一点呢? – Jon 2010-05-28 08:58:24

+1

“long”是一个64位的有符号整数,值为1.2E25的值很大以适应它。 (最大值为9,223,372,036,854,775,807 = 2^63 - 1) – 2010-05-28 09:00:39

+0

不是双倍1.7E +/- 308(15位数)的大小http://msdn.microsoft.com/en-us/library/s3f49ktz.aspx – Dimitar 2010-05-28 09:06:05

1

您可能需要阅读the Floating-Point Guide了解如何doubles工作。

基本上,仅double具有精度约16个十进制数字。在10^25的数量级上,1.0的增加低于精度阈值并且会丢失。由于二进制表示,这可能不明显。

2

要在对方的回答拓展您可以对双最小的增加是最后的地方,或ULP一个单位,为双是浮点类型,那么的ULP的大小而变化,在1E + 25这将约为1E + 10。

,你可以看到1比1E + 10递增真的还不如什么都不添加。这正好是double的功能,所以如果你尝试了10^25倍,那么它无关紧要,除非你尝试增加至少1 ULP

如果通过ULP递增是有用的,你可以做该铸造的位长并回到这里是一个快速的扩展方法来做到这一点

public static double UlpChange(this double val, int ulp) 
    { 
    if (!double.IsInfinity(val) && !double.IsNaN(val)) 
    { 
     //should probably do something if we are at max or min values 
     //but its not clear what 
     long bits = BitConverter.DoubleToInt64Bits(val); 
     return BitConverter.Int64BitsToDouble(bits + ulp); 
    } 
    return val; 
    } 
0

该会工作的最小增量为2^30 + 1,它实际上将2^31增加了一倍。您可以测试这种事情很轻松地与LINQPad:

double inc = 1.0; 
double num = 1.212e25; 
while(num+inc == num) inc*=2; 

inc.Dump(); //2147483648 == 2^31 
(num+inc == num).Dump(); //false due to loop invariant 
(num+(inc/2.0) == num).Dump();//true due to loop invariant 
(num+(inc/2.0+1.0) == num).Dump();//false - 2^30+1 suffices to change the number 
(num+(inc/2.0+1.0) == num + inc).Dump();//true - 2^30+1 and 2^31 are equiv. increments 
((num+(inc/2.0+1.0)) - num == inc).Dump();//true - the effective increment is 2^31 

由于双基本上是用有限精度的二进制数,这意味着尽可能小的增量将自己永远是二的幂(这个增量可可以直接从double的位模式来确定,但是如果使用上面的循环,可能会更清晰,因为它可以在float,double,double和其他浮点表示(它们不在.NET中存在)之间便携。