如何将双打加倍到n位小数c ++

时间:2014-09-01 17:11:35

标签: c++

我正在努力将如何正确地将c ++中的计算结果(双精度)舍入到n位小数。在尝试标准方法时(将数字乘以10 ^ n,使用'round'函数得到最接近的长整数,然后将该结果除以10 ^ n并重铸为double,如下所述: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个小数位的float或double转换为第(n + 1)个十进制数字正确的表示。现在,假设y的十进制表示中的累积误差(e)是&lt;&lt; 1.0E-(n + 1)(机器epsilon为64位双精度约为2.E-16),圆函数给出不良结果的唯一时间是当y的第(n + 1)位为5时,但是十进制近似给出第(n + 1)位为4,第(n + 2)位为> = 5。事实上,在我给出的例子中,y到15位的十进制近似值是124.564999999999984 - 只是这种病态情况。圆函数必须只考虑这些情况。

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

1 个答案:

答案 0 :(得分:-2)

使用双舍入。第一轮将使您接下来的最后一位数字达到预期效果。添加一个非常小的偏移量来抵消二进制浮点数低于实际所需值的趋势,然后再次舍入。

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

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