如果我有这样的内容:
long x = 1/2;
这不应该被舍入到1吗?当我在屏幕上打印时,它显示为0。
如果我有这样的内容:
long x = 1/2;
这不应该被舍入到1吗?当我在屏幕上打印时,它显示为0。
这里进行整数除法,会将小数点右侧的所有内容截断。
(a / b) * b + a % b == a
,并且保证如果a和b都是正数,则a / b
和a % b
将是非负数。如果a和/或b为负,则符号是实现定义的(标准,5.6)。我手头没有C或Java标准文档。 - David Thornley它不能四舍五入,因为它从未处于可以四舍五入的状态
表达式“1/2”在分配给long之前从未是0.5
现在,long x = 1.0/2.0
因为在分配之前右侧的表达式有效进行四舍五入。除非你得到0.499999999999997...
long x = 1.0 / 2.0 + 0.5
。虽然在这种情况下得到0.499999999999997...作为结果可能会让人感到惊讶,但即使如此,这也不会有所帮助。除非不将浮点数四舍五入为整数,否则可能没有任何方法可以解决这个问题。 - UncleBens(1.0/6.0)*3.0+0.5
这样使用了二进制中无法精确表示的数字,那么得到的结果就不准确了,这种情况下我就不会感到惊讶了。 - David Thornley这个问题之前已经在这个网站上回答过了,你正在进行整数除法,如果你想得到0.5,请使用以下方法:
double x = (double)1/2;
你将会得到值为0.5
。
有很多不同的舍入约定,最常见的是向+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
哪种舍入方式是向负无穷大取整,这也是Python所做的(或者至少是Python 2.5中所做的)。
如果我们使用符号-幅度表示,那么截断将是正确的词语,但是二进制补码已成为事实上的标准数十年。
在C和C++中,我期望虽然通常称为截断,但实际上此细节在标准中是未定义的,并留给实现 - 这是允许编译器在平台上使用最简单和最快的方法的借口(处理器除法指令自然执行的操作)。但只有当你有负数时才会出现问题 - 我还没有看到任何语言或实现会给出5/2 = 3。
我不知道Java标准说什么。 Python手册指定“floor”除法,这是一个常用的朝向负无穷大取整的术语。
编辑
额外说明-根据定义,如果a / b = c余数d,则a =(b * c)+ d。为了使其成立,您必须选择适合您的舍入约定的余数。
人们往往认为余数和模数是相同的,但对于带符号值,它们可以不同-具体取决于舍入规则。模数值定义永远不为负,但余数可以为负。
我怀疑 Python 的向负无穷取整规则是为了确保单个 % 运算符既可以作为余数又可以作为模运算符。在 C 和 C++ 中,% 的含义(余数或模)是(没错,你猜对了)实现定义的。
Ada 实际上有两个不同的运算符 - mod 和 rem。由于除法需要向零舍入,所以 mod 和 rem 会给出不同的结果。
a % b
必须是非负的,因此5 / 3
不可能是3,否则5 % 3
将会是-4。它建议在处理负数时向零舍入商,但这是由实现定义的。 - David Thornley