fmod十进制数的最佳方法是什么?

时间:2013-07-09 03:46:40

标签: c math floating-point double

我的问题是通过mod计算得到最准确的结果,我得到了剩余答案来进行另一次舍入计算,所以我确实需要一个准确的结果。

double a = 0.12345678...(may with many digits);

double b = fmod(a, 0.01);

结果b可能不准确处理二进制存储问题。

我是否必须考虑使用float来提高准确性。 或者我只是将数字从小数点移动到整数

double a = 12345678.0;

感谢

2 个答案:

答案 0 :(得分:4)

首先,任何严格的fmod实现都会以单/双/无论精度回答最接近余数的浮点,就好像以无限精度执行除法一样。 ( 注意 :感谢@EricPostpischil 重新发布)

虽然,这太晚了。 0.01的二进制浮点内部表示并不完全像您已经知道的那样代表1/100。

让我们来看看错误是如何累积的。

你想知道一个部门的剩余部分,比如a % b = c

您有不精确的陈述a1和b1,并且您知道这些陈述的错误界限:a1=a+ea1abs(ea1) < eab1=b+eb1abs(eb1) < eb

关于错误绑定a1 % b1 = c1 c1=c+ec1(确切操作),abs(ec1) < ec,您能说些什么?

a = q * b + c.
a1 = q1 * b1 + c1.
a+ea1 = (q+eq1)*(b+eb1) + (c+ec1).
ea1 = eq1*(b+eb1) + q*eb1 + ec1.
ec1 = ea1 - q*eb1 - eq1*(b+eb1).
ec >= max( ea , abs(q)*eb , eq*abs(b) , eq*eb).
ec <= ea + abs(q)*eb + eq*abs(b) + eq*eb.

您可以通过提高表示精度(单,双,扩展,四重,任意精度......)来控制eaabs(q)*eb

但这个平等中的重要术语是eq*abs(b),因为如果商可以一个,那么误差的界限是ec > b

当然,商可以一个一个,这样的情况非常容易构建。 默认情况下,c=0a1代表a ea1<0b1代表b超出eb1>0并且你已经完成了,即使是小商数和准确的精确度,你也得到eq1 = -1

不要认为仔细控制舍入模式,例如获取ea1 > 0(过量)和eb1 <= 0(默认)会在所有情况下保护你,因为我们可以构造相反的情况

b - smallValue < c < b

不要尝试remainder fmod的变量而不是截断,这只会将问题移近完美平局(当精确分割a / b为1的倍数时) / 2)。

通过对错误界限的仔细分析,您可以回答ec的估计并确定可能不正确的商数q舍入的不良情况(当a1/b1接近整个int时),或abs(q)*eb达到1,或ea>=b

在不好的情况下,您可以安排提出异常,并以更高的精度重新开始生成a1b1,但在边缘情况c=0中,没有保证收敛,即使是任意精确的。

答案 1 :(得分:0)

如果我确实理解了您的问题,您需要fmoddouble的结果。正如Pascal Couq在评论中所描述的那样fmod原型是double fmod(double x,double y);,你可以这样做:

#include<stdio.h>
#include<math.h>
int main()
{
  double a = 12.1649232848373633242;
  double b = 1.234;
  double c;
  setbuf(stdout,NULL);
  c = fmod(a,b);

  printf("%.13f",c);//.13 in the format specifiers here describes the number of decimal places upto which you want to get the value .
  return 0;
}