C# 为什么模运算符不适用于c中的双精度?

C# 为什么模运算符不适用于c中的双精度?,c#,.net,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 这里发生了什么 我尝试了数学。IEEERemainderdouble,double,但也没有返回0。这是怎么回事 另外,顺便问一下,在C中查找余数最合适的方法是什么?由于其存储格式,doubles无法准确地存储输入或显示

考虑这一点:

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

这里发生了什么

我尝试了数学。IEEERemainderdouble,double,但也没有返回0。这是怎么回事


另外,顺便问一下,在C中查找余数最合适的方法是什么?

由于其存储格式,doubles无法准确地存储输入或显示的每个值。数字的人工表示通常采用十进制格式,而双精度表示则基于双精度系统

在double中,120被精确地存储,因为它是一个整数值。但0.05不是。双精度近似于它所能代表的最接近0.05的数字。0.5是2 1/2的幂,因此可以精确存储,并且不会出现舍入误差

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

可以帮助你理解为什么你会得到这些奇怪的结果。浮点数有一个特殊的精度。只需尝试以下查询并查看结果:


你可以这样做:

double a, b, r;

a = 120;
b = .05;

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

这应该会有所帮助

模数只能与整数一起使用。其余部分来自欧几里得除法。使用double,您可能会得到意想不到的结果


请参见

我相信,如果您尝试同样的方法处理decimal,它将正常工作。

这就是我们使用的

 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);
    }

了解你想要达到的目标会很有趣。将模与浮点数结合使用从来都不是一个好主意,因为答案已经说明了这一点。不同的语言,但问题是-浮点错误-是相同的,你可以安全地使用带小数的模。双精度始终是一个精确的值。确定其值的操作可能不精确。双a=0.1;->a的精确值可能与数学0.1略有不同。双b=0.125;->b的精确值与数学上的0.125相同。使用decimal仍然是个好主意。可能略有不同的精确值==不精确。@chux:每个数字值都有其分辨率。此上下文中的“精确”表示该值在您输入或显示时准确存储。整数是精确的值。如果在代码中键入7,例如常量,则它不会在后台存储6.99999999999999。小数也一样。双打是不同的。由于其存储格式,它无法准确存储输入/显示的值。双精度值永远不会是准确值,这是绝对的浪费。考虑到C使用IEEE754,这个答案可以大大提高。@Bathsheba:实现IEEE754无助于使双精度存储精确的十进制值。请参阅我最后一条关于使用十进制和双精度存储格式输入/显示的值之间的差异的评论。如果你不相信我说的话,用问题中的代码自己复制它。
 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);
    }