为什么模数运算符在c#中不能用于double?

时间:2009-05-25 12:34:24

标签: c# .net

考虑一下:

double x,y;
x =120.0;
y = 0.05;

double z= x % y;

我试过这个并且期望结果为0,但它出来了0.04933333。

然而,

x =120.0;
y = 0.5;
double z= x % y;

确实给出了正确的0结果。

这里发生了什么?

我试过了Math.IEEERemainder(double, double),但它也没有返回0。这是怎么回事?

另外,另外,在C#中找到余数最合适的方法是什么?

6 个答案:

答案 0 :(得分:15)

由于其存储格式,double无法完全按照输入或显示的方式存储每个值。数字的人类表示通常是十进制格式,而double s基于双系统。

double中,120被精确存储,因为它是一个整数值。但是0.05不是。双精度近似为它可以表示的最接近0.05的数字。 0.521/2)的强大功能,因此可以精确存储,并且不会出现舍入错误。

要使所有数字与在十进制系统中输入/显示的方式完全相同,请改用decimal

decimal x, y;
x = 120.0M;
y = 0.05M;

decimal z = x % y;  // z is 0

答案 1 :(得分:10)

您可以执行以下操作:

double a, b, r;

a = 120;
b = .05;

r = a - Math.floor(a / b) * b;

这应该有帮助;)

答案 2 :(得分:1)

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems可以帮助您了解为什么会得到这些“奇怪”的结果。浮点数可以具有特定的精度。只需尝试这些查询并查看结果:

0.5 in base 2

0.05 in base 2

答案 3 :(得分:1)

我相信如果您使用decimal尝试相同的操作,它将正常工作。

答案 4 :(得分:0)

模数只能与整数一起使用。剩下的部分来自欧几里德分部。使用double,您可以获得意想不到的结果。

请参阅this article

答案 5 :(得分:0)

这就是我们使用的.. :)

 public double ModuloOf(double v1, double v2)
    {
        var mult = 0;

        //find number of decimals
        while (v2 % 1 > 0)
        {
            mult++;
            v2 = v2 * 10;
        }

        v1 = v1 * Math.Pow(10, mult);

        var rem = v1 % v2;
        return rem / Math.Pow(10, mult);
    }