C#中"%"操作对数字类型double的含义

Ser*_*gey 8 c# modulo

最近我发现C#的运算符%适用于double.尝试了一些事情,毕竟想出了这个测试:

class Program
{
    static void test(double a, double b)
    {
        if (a % b != a - b * Math.Truncate(a / b))
        {
            Console.WriteLine(a + ", " + b);
        }
    }
    static void Main(string[] args)
    {
        test(2.5, 7);
        test(-6.7, -3);
        test(8.7, 4);
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

这个测试中的一切都有效.是否a % b总是等同于a - b*Math.Round(a/b)?如果没有,请向我解释这个运营商是如何运作的.

编辑:回答詹姆斯L,我明白这是一个模数运算符和一切.我很好奇它是如何使用双重的,我理解的整数.

Dav*_*nan 8

模数运算符以与整数相同的方式处理浮点值.所以考虑一个简单的例子:

4.5 % 2.1
Run Code Online (Sandbox Code Playgroud)

现在,4.5/2.1约等于2.142857

因此,除法的整数部分是2.从4.5减去2*2.1,你有剩余的0.3.

当然,这个过程受浮点表示问题的影响所以要小心 - 你可能会看到意想不到的结果.例如,在Stack Overflow上看到这个问题:浮点运算 - 双类型上的模运算符


%b是否总是等于a - b*Math.Round(a/b)?

不它不是.这是一个简单的反例:

static double f(double a, double b)
{
    return a - b * Math.Round(a / b);
}

static void Main(string[] args)
{
    Console.WriteLine(1.9 % 1.0);
    Console.WriteLine(f(1.9, 1.0));
    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

至于如何指定模数运算符的精确细节,你需要参考C#规范 - earlNameless的答案为你提供了一个链接.

根据我的理解,a % b它基本上等效,模数浮点精度为a - b*Math.Truncate(a/b).

  • 当`a`和`b`是肯定的时候肯定是正确的.我怀疑所有情况都是如此,但我不是100%肯定. (3认同)
  • 不它不是.用Trunc替换Round,你应该在那里,肯定是积极的'a`和`b`. (2认同)

ear*_*ess 5

来自C# 语言规范第 200 页:

浮点余数:

float operator %(float x, float y); 
double operator %(double x, double y); 
Run Code Online (Sandbox Code Playgroud)

下表列出了非零有限值、零、无穷大和 NaN 的所有可能组合的结果。在表中,x 和y 是正的有限值。z 是 x % y 的结果,计算为 x – n * y,四舍五入到最接近的可表示值,其中 n 是小于或等于 x / y 的最大整数。这种计算余数的方法类似于用于整数操作数的方法,但不同于IEC 60559定义(其中 n 是最接近 x / y 的整数)。