5

我想执行一些计算,我希望结果正确到小数点后,比如 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 double,但徒劳无功。

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

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

4

5 回答 5

6

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

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

于 2013-04-10T16:38:03.077 回答
4

您需要再次阅读双精度概念;更仔细

通过double使用 64 位提高了精度。
小数点前的东西比小数点后的更重要。
所以,当你有一个大整数部分时,它会截断较低的精度——这在各种答案中被描述为rounding off.


更新
为了提高精度,您需要使用一些库或更改您的语言。
检查另一个问题:处理大数字的最佳编码语言(50000+ 位)

但是,我会要求您再次重新检查您的意图。


  • 对于具有非常高值的数字(如您的示例中的整数部分超过 10 位),您真的需要 12 位小数吗?
  • 也许你不会真的有大整数部分
    (在这种情况下,这样的代码应该可以正常工作)。
  • 10000000000.123456789但是,如果您正在跟踪一个
  • 如果你的值的整数部分低于10000,你应该没问题。

更新2
如果您必须证明特定公式能够在受约束的错误限制内准确工作,那么要解决的方法是修复您的公式处理,以便引入最少的错误。

例子,

  • 如果你想说,(x * y) / z
  • 尝试类似的东西是谨慎的max(x,y)/z * min(x,y)
  • 而不是,可能会(x * y)double

如果你只有 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

这可能是你比赛的意图。

于 2013-04-10T16:43:14.977 回答
1

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

于 2013-04-10T16:39:13.610 回答
1

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

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

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

于 2013-04-10T16:39:16.930 回答
0

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

cout << setprecision(12) << std::fixed << d << endl;
于 2013-04-10T16:37:27.240 回答