我的问题是从 mod 计算中获得最准确的结果,我得到了一个余数答案来进行另一个舍入计算,所以我确实需要一个准确的结果才能这样做。
double a = 0.12345678...(may with many digits);
double b = fmod(a, 0.01);
结果b
可能是对二进制存储问题的不准确处理。
我是否必须考虑使用float
来提高准确性。或者我只是将数字从小数点移动到整数
double a = 12345678.0;
谢谢
我的问题是从 mod 计算中获得最准确的结果,我得到了一个余数答案来进行另一个舍入计算,所以我确实需要一个准确的结果才能这样做。
double a = 0.12345678...(may with many digits);
double b = fmod(a, 0.01);
结果b
可能是对二进制存储问题的不准确处理。
我是否必须考虑使用float
来提高准确性。或者我只是将数字从小数点移动到整数
double a = 12345678.0;
谢谢
首先,任何认真的 fmod 实现都将以单/双/任何精度回答最接近余数的浮点,就好像以无限精度执行除法一样。(注:改写感谢@EricPostpischil)
不过,那已经太晚了。0.01 的二进制浮点内部表示并不像您似乎已经知道的那样完全表示 1/100。
让我们检查一下错误是如何累积的。
您想知道除法的余数,例如a % b = c
。
您有不精确的表示 a1 和 b1,并且您知道这些表示的错误界限:a1=a+ea1
、abs(ea1) < ea
、b1=b+eb1
、abs(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.
您可以控制ea
并abs(q)*eb
通过提高表示的精度(单精度、双精度、扩展精度、四倍精度、任意精度......)。
但是这个等式中的重要术语是eq*abs(b)
,因为如果商可以减一,那么错误的界限是ec > b
!
当然,商可以减一,这种情况非常容易构造。默认情况下关闭一个表示 ( )或通过过量 ( )关闭一个表示,你就完成了,你c=0
甚至可以得到小商和准确的精度。a1
a
ea1<0
b1
b
eb1>0
eq1 = -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
。
在不好的情况下,您可以安排引发异常,并重新开始生产a1
并b1
提高精度,但在边缘情况下c=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;
}