0

我的问题是从 mod 计算中获得最准确的结果,我得到了一个余数答案来进行另一个舍入计算,所以我确实需要一个准确的结果才能这样做。

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

double b = fmod(a, 0.01);

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

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

double a = 12345678.0;

谢谢

4

2 回答 2

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=0甚至可以得到小商和准确的精度。a1aea1<0b1beb1>0eq1 = -1

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

b - smallValue < c < b

不要尝试将商舍入而不是截断remainder的变体fmod,这只会使问题接近完美平局(当精确除法 a/b 是 1/2 的倍数时)。

通过对误差范围的仔细分析,您可以回答估计ec并识别可能不正确的商舍入的坏情况q(当a1/b1接近整数时),或abs(q)*eb达到 1,或ea>=b

在不好的情况下,您可以安排引发异常,并重新开始生产a1b1提高精度,但在边缘情况下c=0,即使具有任意精度,也不能保证收敛。

于 2013-07-09T17:54:13.517 回答
0

If I do understand your question correctly , you want the results of fmod in double. As described by Pascal Couq in comments that fmod prototype is double fmod(double x,double y); you can do it like this:

#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;
}
于 2013-07-09T09:32:04.200 回答