【问题标题】:how to round up doubles to n decimal places c++如何将双精度数舍入到 n 位小数 c++
【发布时间】:2014-09-02 10:30:50
【问题描述】:

我正在努力解决如何正确地将 c++ 中的计算结果(双精度数)四舍五入到 n 位小数。在尝试标准方法时(将数字乘以 10^n,使用“round”函数得到最接近的长整数,然后将该结果除以 10^n 并重铸为双精度,如下所述:http://en.wikipedia.org/wiki/Rounding),我发现它在应用于计算结果时会产生意想不到的结果(我认为我知道其答案,但显然计算机不同意)。 n=2 的示例:

#include <iostream>
#include "math.h"

int main()
{
   double x 177.95d; //original number
   double y yr;

   y = x*(1.0d-0.3d); //perform a calculation. Should be 124.565
   yr = (double) round(y/.01)*0.01; //round up y for n=2
   printf("rounded value of y = %.2f\n",yr); //prints out 124.56
}

需要明确的是,我知道所涉及的所有数字都没有精确的二进制表示,但我不希望双精度(我相信它具有大约 15 个十进制数字的精度)难以近似5 位有效(十进制)数字以内的数字。由于许多程序都以这种方式舍入数字,我认为这是可能的(对吗?)甚至电子表格也可以这样做......

更新: 显然,我可以通过简单地提高舍入精度来实现这一点。例如:yr = (double) round(y/.0001)*0.0001;似乎对四舍五入到两位小数的数字产生了正确的结果。但是,我不太清楚十进制舍入数字 (n) 与舍入函数中所需零的数量(我们称之为 m)之间的关系。

更新更新: 我想我已经破解了。首先,我注意到双精度的输出流格式化程序已经将十进制表示四舍五入为您请求的任何格式(例如 printf("%.2f\n",12.345) 将产生输出 12.35)。这意味着必须首先将其十进制表示要四舍五入到第 n 位小数的浮点数或双精度数转换为第 (n+1) 位十进制数字正确的表示。现在,假设 y 十进制表示中的累积误差 (e) 为 =5。事实上,在我给出的例子中,y 到 15 位的十进制近似值是 124.564999999999984——就是这样一个病态的情况。轮函数必须简单地考虑这些情况。

因此,我得出结论:四舍五入函数 (double) round(y/1.0E-m)*1.0E-m 中所需的指数最小值 m 保证对于四舍五入到小数点后 n 位的双精度数始终给出可接受的结果是大于等于二:m=n+2。这解释了我第一次更新的积极结果...

【问题讨论】:

  • 浮点数学不精确
  • 计算yr时使用100,而不是0.01
  • 浮点数学是精确的,但不是你想象的那样。它是精确的,但并不准确。没有124.565 值可以完全存储为double0.3 也是如此:您的任何方程式都没有按照您的想法执行。去了解浮点数学是如何工作的,然后回来!
  • 浮点值没有小数位。他们有二进制的地方。因此,您不能将它们四舍五入到特定的小数位数,除非在小数位和二进制位重合的稀疏情况下。如果你想要小数位,你必须使用小数基数。

标签: c++


【解决方案1】:

使用双舍入。第一次四舍五入将使您期望的最后一个数字。添加一个非常小的偏移量以抵消二进制浮点数低于实际所需值的趋势,然后再次舍入。

yr = round((round(y/0.001)+0.1)/10.0)*0.01;

这并不适用于所有情况,但它应该比简单的方法更加一致。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多