我的问题是通过mod计算得到最准确的结果,我得到了剩余答案来进行另一次舍入计算,所以我确实需要一个准确的结果。
double a = 0.12345678...(may with many digits);
double b = fmod(a, 0.01);
结果b
可能不准确处理二进制存储问题。
我是否必须考虑使用float
来提高准确性。
或者我只是将数字从小数点移动到整数
double a = 12345678.0;
感谢
答案 0 :(得分:4)
首先,任何严格的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
(过量)和eb1 <= 0
(默认)会在所有情况下保护你,因为我们可以构造相反的情况
b - smallValue < c < b
不要尝试remainder
fmod
的变量而不是截断,这只会将问题移近完美平局(当精确分割a / b为1的倍数时) / 2)。
通过对错误界限的仔细分析,您可以回答ec
的估计并确定可能不正确的商数q
舍入的不良情况(当a1/b1
接近整个int时),或abs(q)*eb
达到1,或ea>=b
。
在不好的情况下,您可以安排提出异常,并以更高的精度重新开始生成a1
和b1
,但在边缘情况c=0
中,没有保证收敛,即使是任意精确的。
答案 1 :(得分:0)
如果我确实理解了您的问题,您需要fmod
中double
的结果。正如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;
}