确定是否可以用float / double格式精确表示数字

时间:2015-02-20 17:09:39

标签: c# floating-point

如何确定一个数字,例如1.577,是否可以用float或double格式精确表示?

这意味着它是真正的1.577而不是1.566999999999994324等。

编辑: 我正在寻找一个工具,我可以在其中输入一个数字,它将显示它的双重/浮动表示。所以它不仅仅是与c#相关的问题。

3 个答案:

答案 0 :(得分:17)

您可以使用online decimal to floating-point converter。例如,输入1.577,您会得到两个不准确的指示:

1)选中“不精确”框

2)它以双精度浮点转换为1.5769999999999999573674358543939888477325439453125。

对比1.25这样的数字,打印为1.25,并且不检查“不精确”框。

(该转换器还可以检查单精度数字。)

答案 1 :(得分:4)

您已经有了如何明确检查确切表示的答案。此外,能够在没有正式测试的情况下消除许多数字,并在视线上检查短小数部分是可行和有用的。

假设您的数字的十进制表示在N个小数位后终止。例如,对于1.577,N为3。取小数点后的部分,并以整数577查看它。如果数字可以精确表示为二进制分数,则该部分必须是5 ^ N的整数倍。 577不是125的整数倍,因此1.577不能完全表示。

如果你有一个合理的数量,其十进制表示只有几个有效数字,那么如果它通过了这个测试,它就是完全可以表示的。例如,我知道没有计算机化测试,1.625是完全可以表示的。

答案 2 :(得分:1)

嗯,IEEE-754双精度具有53位精度。那么,唯一可以准确表示的数字是:

  • 有理数,
  • 带有终止​​二进制表示,
  • 表示为53位或更少

所以......要弄清楚给定的十进制值是否可以准确表示,以下内容就足够了:

public bool IsExactlyRepresentableAsIeee754Double( decimal value )
{
  // An IEEE 754 double has 53 bits of precision (52 bits of which are explicitly stored).
  const decimal ieee754MaxBits = 0x001FFFFFFFFFFFFF ;

  // move the decimal place right until the decimal's absolute value is integral
  decimal n = Math.Abs(value) ;
  while ( Decimal.Floor(n) != n )
  {
    n *= 10m;
  }

  bool isRepresentable = n <= ieee754MaxBits ;
  return isRepresentable ;
}

但有一点需要注意:decimal跟踪尾随的小数零(详见下文),因此1m1.0m具有不同的二进制表示形式。因此,decimal x = (decimal)(double)1.00m ;之类的往返会导致x具有与1m相同的二进制表示形式,而不是1.00m;

由于小数的内部表示是well documented in the .Net CLR documentation and specs。它的后备存储可以通过方法Decimal.GetBits()随时使用,由4个32位字组成,具体如下:

  

十进制数的二进制表示由1位符号组成,   一个96位整数,和一个用于分割的缩放因子   整数,并指定它的小数部分。   缩放因子隐含地为数字10,提升为指数   范围从0到28。

     

bits是一个四元素长的32位有符号整数数组。

     
      
  • 位[0],位1和位[2]包含低位,中位数和   高位32位的96位整数。

  •   
  • bits [3]包含比例因子和符号,由[the]组成   以下部分:

         
        
    • 0到15位,低位字未使用,必须为零。
    •   
    • 第16位至第23位必须包含0到28之间的指数,表示除以10的幂以除以整数。
    •   
    • 第24至30位未使用,且必须为零。
    •   
    • 第31位包含符号; 0表示正面,1表示负面。
    •   
  •   
     

数值可能有几种可能的二进制表示形式;全部是   同等有效和数字上等同。注意位表示   区分负零和正零。这些值被处理   在所有操作中都是平等的。

所以你可能会变得聪明,并且有点笨拙地加快速度。踢球者decimal跟踪尾随零,因此1m1.00m的二进制表示不同 - 1m表示为 +1,缩放为10 0功能 的; 1.00m表示为+100,缩放为10 2 。这使事情变得复杂。