9

如果我有类似的东西:

long x = 1/2;

这不应该四舍五入到1吗?当我在屏幕上打印它时,它显示为 0。

4

6 回答 6

30

它正在进行整数除法,将所有内容截断到小数点右侧。

于 2010-02-02T20:34:50.467 回答
6

整数除法起源于数论。当你做 1/2 时,你是在问 2 等于 1 多少次?答案永远不会,因此等式变为 0*2 + 1 = 1,其中 0 是商(从 1/2 得到的),1 是余数(从 1%2 得到的)。

正确指出 % 不是数学意义上的真正模数,而是除法的余数。处理负整数时会有所不同。

希望有帮助。

于 2010-02-02T21:26:54.933 回答
5

这个表达式的作用是它首先声明一个 long 称为 x 的存在,然后将右侧表达式的值分配给它。右手边的表达式是 1/2,因为 1 和 2 都是整数,所以这被解释为整数除法。整数除法的结果总是一个整数,所以沿着 5/3 行的东西将返回 1,因为只有一个三适合一个五。那么对于 1/2,有多少个 2 可以放入 1 中?0。

如果您编写诸如 double x = 1/2 之类的内容,这在某些语言中可能会产生一些有趣的输出。在这种情况下,您可能会期望 0.5,但它通常会先计算右侧的整数值,然后再分配并将结果转换为双精度值,从而给出值 0.0

需要注意的是,在进行这种类型转换时,它永远不会对结果进行四舍五入。所以如果你做相反的事情: long x = (long)(1.0/2.0); 然后虽然 (1.0/2.0) 将评估为 0.5,但 (long) 强制转换将强制将其截断为 0。即使我有 long x = (long)(0.9),结果仍然是 0。它只是截断小数点后。

于 2010-02-02T21:16:26.620 回答
4

它不能舍入,因为它永远不会处于要舍入的状态

在赋值给 long 之前,表达式“1/2”永远不会是 0.5

现在,long x = 1.0/2.0因为在赋值之前右边的表达式对舍入有效。除非你得到 0.499999999999997...

于 2010-02-02T20:36:06.717 回答
2

这个问题之前在这个网站上得到了回答,你正在做一个整数除法,如果你想得到 0.5 使用:

double x = (double)1/2;

你会得到 的值0.5

于 2013-12-27T23:58:48.973 回答
1

有许多不同的舍入约定,最常见的是向 +inf 舍入、向 -inf 舍入和向零舍入。很多人认为有一种正确的方法,但他们对这种方法应该是什么都有不同的想法;-)

整数除法没有中间非整数结果,但当然除法是确定性完成的,并且对于特定平台和编译器将始终遵循一种特定的舍入约定。

使用 Visual C++,我得到 5/2 = 2 和 -5/2 = -2,向零舍入。

C、C++ 和 Java 中的舍入通常被称为“截断”——意思是去掉不需要的位。但这可能会产生误导。使用 4 位 2s 补码二进制,执行截断意味着...

 5/2 = 0101/0010 = 0010.1 --> 0010 =  2
-5/2 = 1011/0010 = 1101.1 --> 1101 = -3

这是向 -infinity 四舍五入,这就是 Python 所做的(或至少它在 Python 2.5 中所做的)。

如果我们使用符号幅度表示,截断将是正确的词,但二进制补码几十年来一直是事实上的标准。

在 C 和 C++ 中,我希望虽然它通常被称为截断,但实际上这个细节在标准中没有定义并留给实现 - 允许编译器为平台使用最简单和最快的方法(处理器除法指令是什么)的借口自然是这样)。但是,如果您有负数,这只是一个问题-我还没有看到任何可以给出 5/2 = 3 的语言或实现。

我不知道 Java 标准是怎么说的。Python 手册指定了“地板”除法,这是舍入到 -infinity 的常用术语。

编辑

额外说明 - 根据定义,如果 a/b = c 余数 d,则 a = (b*c)+d。为此,您必须选择余数以适应您的舍入约定。

人们倾向于假设余数和模数是相同的,但是 WRT 有符号值,它们可能是不同的 - 取决于舍入规则。根据定义,模值永远不会是负数,但余数可以是负数。

我怀疑 Python 舍入负无穷大规则旨在确保单个 % 运算符作为余数和模数都有效。在 C 和 C++ 中,% 的含义(余数或模数)是(是的,你猜对了)实现定义的。

Ada 实际上有两个独立的运算符 - mod 和 rem。需要将除法四舍五入到零,因此 mod 和 rem确实给出了不同的结果。

于 2010-02-02T21:36:25.067 回答