你能帮我理解浮点数学中“有效数字”的含义吗?

时间:2017-11-04 13:32:07

标签: c++ floating-point digit

对于我正在学习的内容,一旦我将浮点值转换为十进制值,我需要的“有效数字”是一个固定数字(例如,17为double)。 17总计:小数分隔符之前和之后。

例如,这段代码:

typedef std::numeric_limits<double> dbl;

int main()
{
    std::cout.precision(dbl::max_digits10);
    //std::cout << std::fixed;    

    double value1 = 1.2345678912345678912345;
    double value2 = 123.45678912345678912345;
    double value3 = 123456789123.45678912345;

    std::cout << value1 << std::endl;
    std::cout << value2 << std::endl;
    std::cout << value3 << std::endl;
}

将正确地“显示”17个值:

1.2345678912345679
123.45678912345679
123456789123.45679

但如果我提高cout的精确度(即std::cout.precision(100)),我可以看到17范围之后还有其他数字:

1.2345678912345678934769921397673897445201873779296875
123.456789123456786683163954876363277435302734375
123456789123.456787109375

为什么要忽略它们?它们也存储在变量/ double中,因此它们将在稍后影响整个“数学”(除法,乘法,求和等)。

“有效数字”是什么意思?还有其他......

3 个答案:

答案 0 :(得分:1)

请注意,浮点值不是实数。值之间存在间隙,所有这些额外数字虽然对实数有意义,但并不反映浮点值的任何差异。将浮点值转换为文本时,使用std::numeric_limits<...>::max_digits10数字可确保您可以将文本字符串转换回浮点并获取原始值。额外的数字不会影响结果。

当您要求更多数字时,您看到的额外数字是转换算法尝试执行您所要求的结果。该算法通常只是提取数字直到达到所需的精度;它可以写成在写入max_digits10 digits之后开始输出零,但这是一个没有人烦恼的额外复杂因素。这不会有帮助。

答案 1 :(得分:1)

只是为了添加 Pete Becker 的答案,我认为你会混淆找到二进制尾数的精确十进制表示的问题,找到某些十进制表示唯一表示二进制尾数的问题(给定一些固定的舍入方案)。

现在,关于第一个问题,你总是需要有限数量的十进制数来准确表示二进制尾数(因为2除以10)。

例如,您需要18个十进制数字完全代表二进制1.0000000000000001,以十进制为1.00000762939453125

但是您只需要17个数字就可以将其唯一地表示为1.0000076293945312,因为没有其他数字具有精确值1.0000076293945312xyz...,其中0 <= x <5可以作为double存在(更确切地说,下一个和先前可准确表示的值为1.00000762939453147204460492503130808472633361816406251.0000076293945310279553950749686919152736663818359375)。

当然,意味着给定一些十进制数,你可以忽略17日之后的所有数字;它只是意味着如果你应用相同的舍入方案用于在第17个位置产生小数并将其分配回一个双倍,你将获得相同的原始双倍。

答案 2 :(得分:1)

  

你能帮助我理解浮点数学中“有效数字”的含义吗?

对于FP数字,如数学实数,有效数字是不以0开头的值的前导数字,然后根据上下文,1)小数点,2)最后一个非零数字,或3)最后一个打印数字。

123.         // 3 significant decimal digits
123.125      // 6 significant decimal digits
0.0078125    // 5 significant decimal digits
0x0.00123p45 // 3 significant hexadecimal digits
123000.0     // 3, 6, or 7 significant decimal digits depending on context

当关注十进制有效数字和FP类型如double时。问题通常是&#34;需要或关注多少十进制有效数字?&#34;

几乎所有C FP实现都使用二进制编码,这样所有有限FP都是精确 2的幂和。每个有限FP exact 。通用编码为大多数double提供了53个二进制数字是有意义的 - 所以 53 有效二进制数字 。这看起来像十进制通常是混乱的来源。

// Example 0.1 is not an exact sum of powers of 2 so a nearby value is used.
double x = 0.1;
// x takes on the exact value of 
// 0.1000000000000000055511151231257827021181583404541015625
// aka 0x1.999999999999ap-4
// aka base2: 0.000110011001100110011001100110011001100110011001100110011010
// The preceding and subsequent doubles
// 0.09999999999999999167332731531132594682276248931884765625
// 0.10000000000000001942890293094023945741355419158935546875
//   123456789012345678901234567890123456789012345678901234567890

如上所述,可以说x有超过50个十进制有效数字。然而,该值匹配预期的0.1到16 十进制有效数字。或者,由于前面和后面的可能double值在17位有所不同,可以说x有17 十进制有效数字

  

这意味着什么&#34;有效数字&#34;?

存在有效数字的各种含义,但对于C,有两种常见的含义:

  1. 十进制有效数字的数量double的文字值按预期转换为所有double。通常为15. C将其指定为DBL_DIG且必须至少为10.

  2. 十进制有效数字的数量,需要打印文本值double以区别于另一个double。这通常是17. C将其指定为DBL_DECIMAL_DIG且必须至少为10.

  3.   

    为什么要忽略它们?

    这取决于编码目标。很少是所需的确切值的所有数字。 (DBL_TRUE_MIN可能有752个。)对于大多数应用程序,DBL_DECIMAL_DIG就足够了。在选定的应用中,DBL_DIG会这样做。所以通常是,忽略17点以后的数字不会导致问题。