【问题标题】:How to print upto 100th decimal places accurately of a float or double type variable?如何准确打印浮点型或双精度型变量的小数点后 100 位?
【发布时间】:2016-10-11 18:07:55
【问题描述】:

假设有两个数字 22 和 7。我想打印到答案的小数点后 100 位,它应该看起来像 3.1428571428571428571428571.... 而尝试使用

cout << setprecision(100) << fixed << (22.0/7.0); 

我得到类似 3.142857142857142793701541449991054832935333251953125.......

【问题讨论】:

  • floatdouble 在转换成十进制时都没有那么多有效数字。 Specifically, float has roughly 7 decimal digits of precision, and double has 16.
  • 你可能想试试像 gmp 这样的库。
  • 不要混淆精度(你可以显示多少个小数位)和准确度(有多少个小数位是正确的。)一旦你超过了第十五位有效数字,你还不如随机附加数字。
  • @jaggedSpire 我添加了一个答案。我不知道如何以更好的格式将它放在 cmets 中。所以我放在那里。我收到 SEG 违规。我的问题是我们能不能把整个内容放在一个流中?
  • 还要把事情放在上下文中:以质子半径 (~10 ^ -15 m) 为单位测量太阳系的直径 (4.5 * 10^12 m) 需要 28 个有效数字。即使您可以将一个数字表示为 100 个重要位置,但也不太清楚您为什么要这样做(除了在无意义的忙碌工作中进行练习。)

标签: c++ floating-point double floating-accuracy


【解决方案1】:

通常在 c++ 中,双精度数(两者中较大的一个)存储在 8 个字节中。 这意味着该数字可以包含 2^8*8 = 2^64 个字节(^ = 幂)。 这意味着在保留符号和浮点位置之后,该点之后的最大位数最多为 ~15 位。因此,您必须创建其他方法,然后为该计算加倍。 这是我的参考: https://www.tutorialspoint.com/cplusplus/cpp_data_types.htm

【讨论】:

    【解决方案2】:

    当我尝试时

    int main()
    {
       const long double pi = 22.0/7.0;
       std::cout << std::setprecision(std::numeric_limits<long double>::max()) << pi << '\n';
    }
    

    我遇到了分段泄漏。

    你得到的最大值是:

    int main()
    {
        const long double pi = 22.0/7.0;
        std::cout << std::setprecision(std::numeric_limits<long double>::digits) <<   pi << '\n';
    }
    

    输出是: 3.142857142857142793701541449991054832935333251953125

    【讨论】:

    • 您对第一个示例有何期望? std::numeric_limits&lt;long double&gt;::max()long double 可表示的最大数字(不是有效数字的数量),您将其隐式转换为 int,这是未定义的行为,因为该值不能表示为 intstd::numeric_limits&lt;long double&gt;::digits 是可表示的以 2 为底的位数,而不是十进制数。您将输出比有效数字多得多的数字。
    • 但是我基本上还有一个问题。我提出了问题cmets。我也会放在这里。我收到 SEG 违规。我的问题是我们能不能把整个内容放在一个流中? ——
    • digits10 也是错误的,它是以10为底的位数,可以不加变化地表示。它低于存储值的准确性。由于 C++11 有 max_digits10,它将为您提供唯一存储该类型的任何值所需的有效位数。当然,指数需要另外保存,即通过科学记数法。
    【解决方案3】:

    打印不是问题。代码很好地将商打印为双精度

    cout << setprecision(100) << fixed << (22.0/7.0);
    
    OP's reported result
    3.142857142857142793701541449991054832935333251953125.......
    // My expected result of the double 22.0/7.0
    3.1428571428571427937015414499910548329353332519531250000000....
    

    使用double 数学通常不会为 OP 提供 100 位精度。这就是原因。

    不同的解释方式

    double 通常为 64 位。这给出了多达 264完全可表示数字的组合。考虑double n,d,q; 和划分n/d。这是n,d 的2128 种不同组合,但我们正试图将所有这些结果放入q。许多会导致相同的答案(22.0/11.0 和 14.0/7.0 都生成 2.0)。然而,肯定有超过 264 个不同的数学答案。

    所以 C 四舍五入答案是最好的 - 通常是最接近的 - representable double

    在这种情况下:22.0/7.0,确切地说,不是这 264 个组合之一。
    “最好”是“类似于 3.142857 142857 142793 7015414...”

    double x = 22.0/7.0;
    //  x   3.142857 142857 142793 701...
    
    // 22.0/7.0
    // math 3.142857 142857 142857 142857 
    
    double next_x = nextafter(22.0/7.0, 4.0);
    //      3.142857 142857 143237 790...
    

    【讨论】:

      【解决方案4】:

      试试这个把答案四舍五入到小数点后 100 位。

          double long a,b,n;
          cin>>a>>b;
          n=a/b;
          std::cout << std::fixed;
          std::cout << std::setprecision(100);
          std::cout << n << '\n';
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-09
        • 2021-05-15
        • 2012-06-19
        • 2021-10-27
        • 2011-10-24
        • 2021-07-25
        相关资源
        最近更新 更多