考虑一下:
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#中找到余数最合适的方法是什么?
答案 0 :(得分:15)
由于其存储格式,double
无法完全按照输入或显示的方式存储每个值。数字的人类表示通常是十进制格式,而double
s基于双系统。
在double
中,120
被精确存储,因为它是一个整数值。但是0.05
不是。双精度近似为它可以表示的最接近0.05
的数字。 0.5
是2
(1/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可以帮助您了解为什么会得到这些“奇怪”的结果。浮点数可以具有特定的精度。只需尝试这些查询并查看结果:
答案 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);
}