我最近遇到的似乎是在一段代码中解释我的数学逻辑
if((123/1000) > 0)
出于某种原因,C#声称这是错误的,但如果要逻辑思考,那么0.123 大于0。
是否有任何理由声称0.123小于0?
我已经读过,对于基数为2的double会有比较问题,最好使用基数为10的十进制数。
有人可以启发我吗?
答案 0 :(得分:15)
您的谬论是,您认为结果为0.123
,而0
则为1 + 1
。
C#(以及许多其他类C语言)定义涉及两个整数的操作总是返回一个整数,因此2
将返回2.0
,而不是3 / 2
和{{1} }将返回1
,而不是1.5
。在这种情况下,小数部分被简单地丢弃,因此它总是向零舍入(即,对于正结果,它向下舍入,对于负向的向上舍入)。
虽然这可能有点反直觉,但主要原因是语言/编译器的简单性,执行速度(因为你不需要弄清楚结果的类型),能够使用像{{1这样的运算符如果结果是不同的类型)和历史遗产和惯性,这将无效。
要解决此问题,您需要至少使一个操作数成为一个浮点数(另一个将自动跟随,结果也是如此):
/=
如果您有变量,则可能需要进行类型转换(因为您不能简单地追加// either
if (123.0 / 1000 > 0)
// or
if (123 / 1000.0 > 0)
// or
if (123.0 / 1000.0 > 0)
: - )):
.0
通常的建议在这里也适用:编程时,很少相信你的直觉,因为计算机是奇怪的机器,编程语言有时甚至更奇怪。在某处打印结果或将其分配给变量并检入调试器会向您显示您的期望已关闭: - )
答案 1 :(得分:9)
123和1000是整数,结果小于1,因此它舍入为0.使用此:
123.0/1000.0 > 0.0
它将使用双精度,即你可以有一小部分!
答案 2 :(得分:4)
由于123
和1000
为Int32
,结果必须为Int32
。但由于结果小于1
,因此会自动舍入为0
。
你至少应该使这些数字成为浮点数。
if(123.0/1000.0 > 0.0)
{
if((123.0/1000) > 0)
{
if((123/1000.0) > 0)
{
Console.WriteLine("True"); // Prints True
}
}
}
这是DEMO
。
同时查看此问题Possible Loss of Fraction
答案 3 :(得分:2)
尽管已经回答了这个问题,但没有人对这个问题给出了好的观点,所以我想让它更清楚:
如果您是dividing
或multiplying
int
和float
,您将获得如下结果:
int/int => int
float/int => float
int/float => float
所以,如果你要分开:
123/1000 => 0 (as there is no int number 0.123, it will then set to 0)
123.0/1000 => 0.123 (this dividing is basically saying that I need a float result of dividing)
123/1000.0 => 0.123 (this says the same as previous)
因此规则基本上是 - 如果您使用的是与其使用的类型相同的“上”级别的类型,则计算将转换为该“父”类型。但这一般不能说,就像使用浮动类型一样,它总会被转移到浮点数。以下是更多示例:
long/int => long
double/float => double
double/int => double
如果你想对你的问题有一个回答,那么答案就是:
if(((float)123/1000) > 0)
或
if(((double)123/1000) > 0)
所以它总会计算浮点数(0.123数)
答案 4 :(得分:1)
int / int
是int
- 这意味着123/1000
是0
而不是0.123
,正如您所料 -
因为0不大于0,表达式的计算结果为假!
修复是将其中一个整数作为双 -
if(123.0 / 1000 > 0) <- true
if(123 / 1000.0 > 0) <- true
if(123.0 / 1000.0 > 0) <- true
答案 5 :(得分:0)
使用此:
if((123.0/1000) > 0)
您正试图将int
除以int
。所以你得到整数除法。但你需要使用double。
如果你想分配int变量并获得双重使用:
double doubleNum = (double)intNum1/(double)intNum2;
答案 6 :(得分:-1)
当仅使用整数值进行除法时,结果也将是整数。
如果我没记错的话,小数点后的部分会被删除。
所以你的代码被编译成类似的东西:
a = int(123/1000) <--- evaluates to 0.
if (a > 0) .... <--- false
根据@algreat回答的解决方案是强制其中一个操作数加倍(通过添加.0
。这将强制结果浮动。