C 当y是整数时,fmod()精确吗?

C 当y是整数时,fmod()精确吗?,c,floating-point,C,Floating Point,使用double fmod(double x,double y)并且y是一个整数时,结果似乎总是精确的 (也就是说y是一个精确的整数,这里不表示int) 也许C不需要fmod()在这些选择的情况下提供准确的答案,但在我尝试过的编译器上,结果是准确的,即使x/y的商不能精确表示 当y为整数时,是否需要精确答案 如果没有,请提供一个反例 示例: double x = 1e10; // x = 10000000000 printf("%.50g\n", fmod(x, 100)); // prints

使用
double fmod(double x,double y)
并且
y
是一个整数时,结果似乎总是精确的

(也就是说
y
是一个精确的整数,这里不表示
int

也许C不需要
fmod()
在这些选择的情况下提供准确的答案,但在我尝试过的编译器上,结果是准确的,即使
x/y
的商不能精确表示

  • y
    为整数时,是否需要精确答案
  • 如果没有,请提供一个反例
  • 示例:

    double x = 1e10;
    // x = 10000000000
    printf("%.50g\n", fmod(x, 100));
    // prints 0
    
    x = 1e60;
    // x = 999999999999999949387135297074018866963645011013410073083904
    printf("%.50g\n", fmod(x, 100));
    // prints 4
    
    x = DBL_MAX;
    // x = 179769313486231570...6184124858368
    printf("%.50g\n", fmod(x, 100));
    // prints 68
    
    x = 123400000000.0 / 9999;
    // x = 12341234.1234123408794403076171875
    printf("%.50g %a\n", fmod(x, 100), fmod(x, 100));
    // prints 34.1234123408794403076171875 0x1.10fcbf9cp+5
    
    注:
    我的
    double
    显示为符合IEEE 754 binary64的版本。
    这里不讨论
    printf()
    的限制,只讨论
    fmod()


    [编辑]


    注:通过“是否需要精确答案”,我是问
    fmod()
    结果和数学结果是否完全相同

    fmod的结果总是准确的;
    y
    是否为整数无关紧要。当然,如果
    x
    和/或
    y
    已经是一些实数
    a
    b
    的近似值,那么
    fmod(x,y)
    不太可能完全等于
    a mod b

    IEEE标准754将余数运算
    x REM y
    定义为数学运算
    x-(圆形)(x/y)*y)
    。根据定义,即使中间操作
    x/y
    round(x/y)
    等具有不精确的表示,结果也是精确的


    正如aka.nice所指出的,上面的定义与
    libm
    fmod
    中的库函数
    余数
    相匹配,以不同的方式定义,要求结果具有与
    x
    相同的符号。然而,因为
    fmod
    余数
    之间的差异是
    0
    y
    ,我相信这仍然可以解释为什么结果是精确的。

    这里“精确”是什么意思?就像“匹配数学结果”?你是对的。抱歉,比特sleepy@OliCharlesworth是,“匹配数学结果”+1引用。我想快速直观地解释为什么
    x-(轮(x/y)*y)
    在原始精度范围内总是有一个精确的结果,但它太复杂了,所以我把它从我的答案中漏掉了。我认为没有一个简单的解释。天真地计算
    x轮(x/y)*对于我尝试过的一些极端情况(
    x=pow(2,53)*100
    y=100
    ),y
    fmod(x,y)
    不同。实现必须执行迭代减法之类的技巧,以保持结果在数学上的精确性。我所知道的最佳解释是从减去
    r^n*y
    开始,其中
    r
    是基数,
    n
    是产生结果的指数,其指数与
    x
    的指数相同;这减少了n精度的位数至少为1,并产生一个与
    x
    mod
    y
    一致的值。我怀疑您是通过归纳的方式应用此参数得出结论的,但细节(尤其是当符号翻转时)是一种痛苦。@R..下面的解释如何:让
    R
    成为数学结果。
    x
    y
    都是大于
    R
    的浮点数,因此是
    ulp(R)
    的倍数。因此
    R
    ulp(R)的倍数
    ,因此
    r
    可以精确地表示为浮点数。@PascalCuoq:并不是所有的
    ulp(r)
    的精确倍数都可以表示。例如,
    LLONG_MAX*ulp(r)
    肯定不是。