为什么小数点后的数字全为零?

时间:2013-04-10 16:32:53

标签: c++ c floating-point-precision

我想执行一些计算,我希望结果正确到一些小数位,比如12。 所以我写了一个样本:

#define PI 3.1415926535897932384626433832795028841971693993751
double d, k, h;
k = 999999/(2*PI);
h = 999999;
d = PI*k*k*h;
printf("%.12f\n", d);

但它给出了输出:

79577232813771760.000000000000

我甚至使用了setprecision(),但相同的答案却是指数形式。

cout<<setprecision(12)<<d<<endl;

打印

7.95772328138e+16

也使用了长双,但徒劳无功。

除了在long long int类型中分别存储整数部分和小数部分之外,还有其他方法吗?

如果是这样,可以做些什么来准确地得到答案?

5 个答案:

答案 0 :(得分:6)

double只有大约16位精度的十进制数字。小数点后的所有内容都是无稽之谈。 (事实上​​,该点的最后一个数字或两个数字可能与无限精度计算不一致。)

长双不标准化,AFAIK。可能是在您的系统上它与double相同,或者不再精确。这会让我感到有些惊讶,但它并没有违反任何规定。

答案 1 :(得分:4)

您需要再次阅读Double-Precision个概念; 更仔细

double使用64位提高了精度 小数点之前的东西比之后的东西更重要。
因此,当你有一个大的整数部分时,它将截断较低的精度 - 这在这里以rounding off的形式在各​​种答案中描述。


<强>更新
为了提高精确度,您需要使用一些库或更改您的语言 检查另一个问题:Best coding language for dealing with large numbers (50000+ digits)

然而,我会要求你再次重新检查你的意图。

  • 对于值很高的数字,你真的需要12位小数吗? (在您的示例中,整数部分超过10位数)?
  • 也许你真的没有大整数部分
    (在这种情况下,此类代码应该可以正常工作)。
  • 但如果您要跟踪10000000000.123456789之类的值,则 我对你正在研究的应用程序(天文学?)非常感兴趣。
  • 如果您的值的整数部分在10000之下,那么您应该没问题。

<强> UPDATE2
如果您必须证明特定公式在约束误差限制内准确工作的能力,那么可以采用的方法是修复公式的处理,以便引入最小的误差。

实施例,

  • 如果你想说,(x * y) / z
  • 尝试像max(x,y)/z * min(x,y)
  • 这样的做法是明智的
  • 而不是(x * y)之后可能溢出的原始形式,如果不符合double的16位小数,则会失去精确度

如果您只有2位精度,

.               2-digit       regular-precision
 `42 * 7        290           297
 (42 * 7)/2     290/2         294/2
 Result ==>     145           147

       But ==>  42/2 = 21
                21 * 7 = 147

这可能是您竞赛的目的。

答案 2 :(得分:1)

大多数计算机使用的双精度二进制格式只能容纳大约16位数字,之后您将进行四舍五入。见http://en.wikipedia.org/wiki/Double-precision_floating-point_format

答案 3 :(得分:1)

浮点值具有数字限制范围。仅仅因为您的“PI”值的数字是double的六倍,所以支持不会改变硬件的工作方式。

典型的(IEEE754)double将产生大约15-16个小数位。无论是0.12345678901235,1234567.8901235,12345678901235或12345678901235000000000,还是其他一些变体。

换句话说,是的,如果你完全计算你的计算,你会得到很多小数位,因为pi永远不会结束。在计算机上,无论您使用什么输入值,您都会获得大约15-16位数字 - 所有更改都是小数位所在的序列中的位置。要获得更多,您需要“大量支持”,例如Gnu Multiprcession(GMP)库。

答案 4 :(得分:0)

你正在寻找std::fixed这告诉ostream 不是使用指数形式。

cout << setprecision(12) << std::fixed << d << endl;