我最近在一段代码中遇到了似乎使我的数学逻辑感到困惑的东西
if((123/1000) > 0)
出于某种原因,C# 声称这是错误的,但如果从逻辑上思考,0.123大于0。
有什么理由声称 0.123 小于 0?
我已经读过,以 2 为底的 double 会有一个比较问题,最好使用以 10 为底的小数。
有人可以启发我吗?
你的谬论是你认为结果是0.123
,而结果却是0
。
C#(和许多其他类似 C 的语言)定义涉及两个整数的运算总是返回一个整数,因此1 + 1
将 return 2
, not2.0
并且3 / 2
将 return 1
, not 1.5
。在这种情况下,小数部分被简单地丢弃,因此它总是向零舍入(即,对于正结果,它向下舍入,对于负结果,它向上舍入)。
虽然这可能有点违反直觉,但主要原因是语言/编译器的简单性、执行速度(因为您不需要弄清楚结果的类型)、使用类似/=
which的运算符的能力结果是不同的类型)以及历史遗产和惯性。
要解决这个问题,您需要将至少一个操作数设为浮点数(另一个会自动跟随,结果也会如此):
// either
if (123.0 / 1000 > 0)
// or
if (123 / 1000.0 > 0)
// or
if (123.0 / 1000.0 > 0)
如果你有变量,你可能需要一个类型转换(因为你不能简单地附加.0
:-)):
if ((double)a / b > 0)
通常的建议在这里也适用:在编程时,很少相信你的直觉,因为计算机是奇怪的机器,而编程语言有时甚至更陌生。将结果打印在某处或将其分配给变量并检查调试器会向您表明您的期望已偏离 :-)
123 和 1000 是整数,结果小于 1,因此四舍五入为 0。使用这个:
123.0/1000.0 > 0.0
它将使用双精度,即你可以有一个分数!
尽管已经回答了这个问题,但没有人对这个问题给出好的观点,所以我想让它更清楚:
如果你是dividing
ormultiplying
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 数)
int / int
是一个int
- 这意味着这123/1000
不是你0
所0.123
期望的 -
由于 0 不大于 0,因此表达式的计算结果为 false!
解决方法是将其中一个整数设为双精度 -
if(123.0 / 1000 > 0) <- true
if(123 / 1000.0 > 0) <- true
if(123.0 / 1000.0 > 0) <- true
用这个:
if((123.0/1000) > 0)
您正试图int
除以int
. 所以你得到整数除法。但是你需要使用双。
如果你想定义 int 变量并获得双重使用:
double doubleNum = (double)intNum1/(double)intNum2;
仅使用整数值进行除法时,结果也将是整数。
如果我没记错的话,小数点后的部分会被去掉。
所以你的代码被编译成类似的东西:
a = int(123/1000) <--- evaluates to 0.
if (a > 0) .... <--- false
根据@algreat 答案的解决方案是强制其中一个操作数为双精度(通过添加.0
. 这也将强制结果为浮点数。