我的双重值等于1.212E + 25
当我把它扔到文本时,我做myVar.ToString(“0000000000000000000000”)
问题是,即使我做myVar ++ 3或4倍,价值也似乎保持不变。
为什么?
答案 0 :(得分:3)
这是因为双精度不够。它根本无法容纳那么多有效数字。
它不适合长,但可能是十进制。
但是......你真的需要这种精确度吗?
答案 1 :(得分:2)
要扩展另一个答案,你可以对double进行最小的增加是最后一个位置的一个单位,或ULP,因为double是一个浮点类型,然后ULP的大小发生变化,在1E + 25它会约1E + 10。
正如您所看到的,与1E + 10相比,增加1真的可能不会增加任何东西。这正是双重会做的事情,所以如果你试了10 ^ 25次就没关系它仍然不会增加,除非你试图增加至少1 ULP
如果通过ULP递增是有用的,你可以通过将位转换为long来实现这一点,这里是一个快速扩展方法来做到这一点
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;
}
答案 2 :(得分:1)
您可能需要阅读the Floating-Point Guide以了解doubles
的工作原理。
基本上,double
只有大约16个十进制数字的精度。在10 ^ 25的量级上,增加1.0低于精度阈值并且丢失。由于二进制表示,这可能不是很明显。
答案 3 :(得分:1)
double
(Double
)约有16位精度,long
(Int64
)约有18位数。
这些似乎都没有足够的精确度满足您的需求。
但是decimal
(Decimal
)最多可容纳30位精度。虽然这似乎足以满足您的需求,但如果您的需求变得更大,我建议您谨慎行事。在这种情况下,您可能需要第三方数字库。
相关的StackOverflow条目是:
How can I represent a very large integer in .NET?
Big integers in C#
答案 4 :(得分: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本质上是一个精度有限的二进制数,这意味着最小可能的增量本身总是2的幂(这个增量可以直接从double的位模式确定,但它可能更清晰使用上面的循环来执行此操作,因为它可以在float
,double
和其他浮点表示(.NET中不存在)中移植。