Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#-增加一个双精度值(1.212E+;25)_C#_.net_Types_Floating Point - Fatal编程技术网

C#-增加一个双精度值(1.212E+;25)

C#-增加一个双精度值(1.212E+;25),c#,.net,types,floating-point,C#,.net,Types,Floating Point,我有一个双倍值,等于1.212E+25 当我将它抛出到文本时,我执行myVar.ToString(“0000000000000000”) 问题是,即使我使用myVar++3或4倍,该值似乎保持不变 为什么会这样?那是因为双精度是不够的。它不能容纳那么多有效数字 它不适合长字符,但可能适合小数 但是。。。您真的需要这样的精度吗?您可能需要阅读以了解倍增的工作原理 基本上,double只有大约16位小数精度。当震级为10^25时,1.0的增量低于精度阈值并丢失。由于二进制表示,这可能不明显。要展开另

我有一个双倍值,等于1.212E+25

当我将它抛出到文本时,我执行myVar.ToString(“0000000000000000”)

问题是,即使我使用myVar++3或4倍,该值似乎保持不变


为什么会这样?

那是因为双精度是不够的。它不能容纳那么多有效数字

它不适合长字符,但可能适合小数

但是。。。您真的需要这样的精度吗?

您可能需要阅读以了解
倍增的工作原理


基本上,
double
只有大约16位小数精度。当震级为10^25时,1.0的增量低于精度阈值并丢失。由于二进制表示,这可能不明显。

要展开另一个答案,您可以对double进行的最小增加是最后一位的一个单位,或ULP,因为double是浮点类型,那么ULP的大小会发生变化,在1E+25时,它将大约为1E+10

正如您所看到的,与1E+10相比,增加1实际上可能等于不增加任何内容。这正是double所能做的,所以如果你尝试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^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中不存在)。

double
double
)可容纳约16位精度和约18位长度(
Int64

这两种方法似乎都没有足够的精度满足您的需要

但是,
decimal
decimal
)最多可容纳30位精度。尽管这似乎足以满足您的需要,但我建议您在您的需求进一步增长时谨慎。在这种情况下,您可能需要第三方数字库

相关StackOverflow条目为:


如果将其设为长整数,那么就可以了吗?a
long
是一个64位有符号整数,其值1.2E25太大,无法放入其中。(最大值为9223372036854775807=2^63-1)不是双1.7E+/-308(15位)的大小@Dimitar:是的,范围最多可以达到10^308…但如果精度只有15位,25位数字加1怎么会有区别呢?@Dimitar没有人提出过相反的说法