C语言中对两个正double值调用remainder为何返回负数?
结果不符合预期的原因
你运行的代码如下:
double a = 9.92; double b = 2.00; printf("%.2lf, %.2lf, %.2lf", a, b, remainder(a, b));
出现该现象的核心原因有两个:
1. remainder函数的计算规则和你预期的取模逻辑不一致
你预期得到的1.92是fmod函数的计算结果,C标准中两个函数的逻辑有明确差异:
fmod(x, y):计算逻辑为x - trunc(x/y) * y,其中trunc代表向0取整,返回结果的符号和x一致,绝对值一定小于y的绝对值。按该规则计算,fmod(9.92, 2.0) = 9.92 - 4*2 = 1.92,完全匹配你的预期。remainder(x, y):计算逻辑为x - rint(x/y) * y,其中rint代表取最接近输入的整数,若输入恰好落在两个整数中间则取偶数,返回结果的绝对值一定小于等于|y/2|。你的用例中9.92 / 2 = 4.96,最接近的整数是5,按规则计算得到9.92 - 5*2 = -0.08,本身就是符合remainder设计逻辑的正常结果。
2. 双精度浮点数的存储精度误差
十进制的9.92无法被二进制格式的double类型精确存储,变量a实际存储的是和9.92非常接近但略小的数值,这个微小的误差在计算后被放大,最终保留两位小数输出时就会显示为你观测到的-0.18。
如果要得到你预期的1.92的结果,直接把代码中的remainder替换为fmod即可。
内容的提问来源于stack exchange,提问作者frowit
相关产品推荐
相关产品推荐

