jjm*_*elo 43 ruby python integer-division perl6 raku
在我测试的语言中,- (x div y )不等于-x div y; 我已经//在Python中,/在Ruby中,div在Perl 6中进行了测试; C有类似的行为.
这种行为通常是根据规范,因为div通常被定义为舍入向下分工的结果,但它不从的观点算术点做出很大的意义,因为它使div行为以不同的方式取决于标志,它引起混乱,如这篇文章如何在Python中完成.
这个设计决策背后是否有一些特定的理由,或者只是div从头开始定义?显然Guido van Rossum在博客文章中使用了一致性论证,解释了它是如何在Python中完成的,但如果你选择整理,你也可以有一致性.
chi*_*chi 44
理想情况下,我们希望为每个操作提供两个操作,div并且mod满意b>0:
(a div b) * b + (a mod b) = a0 <= (a mod b) < b(-a) div b = -(a div b)然而,这是数学上的不可能性.如果以上都是真的,我们就会有
1 div 2 = 0
1 mod 2 = 1
Run Code Online (Sandbox Code Playgroud)
因为这是(1)和(2)的唯一整数解.因此,我们也可以通过(3),
0 = -0 = -(1 div 2) = (-1) div 2
Run Code Online (Sandbox Code Playgroud)
其中,(1),暗示
-1 = ((-1) div 2) * 2 + ((-1) mod 2) = 0 * 2 + ((-1) mod 2) = (-1) mod 2
Run Code Online (Sandbox Code Playgroud)
制造(-1) mod 2 < 0哪些与(2)相矛盾.
因此,我们需要在(1),(2)和(3)中放弃一些属性.
一些编程语言放弃了(3),并向下div舍入(Python,Ruby).
在一些(罕见的)情况下,该语言提供多个除法运算符.例如,在Haskell中,我们只div,mod满足(1)和(2),类似于Python,我们也只quot,rem满足(1)和(3).后一对运营商将分割为零,以返回负剩余的价格为例,例如,我们有(-1) `quot` 2 = 0和(-1) `rem` 2 = (-1).
C#也放弃了(2),并允许%返回负余数.相干地,整数除法向零舍入.从C99开始,Java,Scala,Pascal和C也采用这种策略.
Chr*_*tix 38
浮点运算由IEEE754定义,并考虑了数字应用程序,默认情况下,以非常严格定义的方式舍入到最接近的可表示值.
计算机中的整数操作不是由一般国际标准定义的.语言(特别是C系列的语言)授予的操作倾向于遵循底层计算机提供的任何操作.有些语言比其他语言更有力地定义某些操作,但为了避免在他们那个时代的可用(和流行)计算机上实现过度困难或缓慢,将选择一个非常接近其行为的定义.
出于这个原因,整数运算倾向于在溢出(对于加法,乘法和向左移位)上回绕,并且在产生不精确的结果时(对于除法和向右移位)向负无穷大舍入. 这两个都是在二进制补码二进制算术中它们各自末端的简单截断 ; 处理角落箱的最简单方法.
其他答案讨论与语言可能提供的余数或模数运算符的关系.不幸的是他们倒退了. 余数取决于除法的定义,而不是相反的方式,而模数可以独立于除法来定义 - 如果两个参数恰好是正的并且除法向下舍入,它们的结果是相同的,所以人们很少注意到.
大多数现代语言提供余数运算符或模数运算符,很少提供.库函数可以为关心差异的人提供其他操作,即剩余部分保留被除数的符号,而模数保留除数的符号.
Pau*_*mas 12
因为整数除法的含义是完整答案包括余数.
aba*_*ert 12
维基百科有一篇很好的文章,包括历史和理论.
只要一种语言满足欧几里德划分属性(a/b) * b + (a%b) == a,地板划分和截断划分都是连贯的和算术上合理的.
当然,人们喜欢争辩说一个人显然是正确的而另一个人显然是错的,但它更具有圣战的特征,而不是一个明智的讨论,而且它通常更多地与他们早期首选语言的选择有关.其他.他们也经常倾向于主张他们的选择%,即使先选择/然后选择%匹配可能更有意义.
% 遵循除数的标志显然是70%的学生猜测mod或modulo不是remainder.modulo而不是remainder(即使这实际上反对他们的观点).mod而不是modulo,因此它应该遵循Fortran的区别.(这可能听起来很愚蠢,但可能是C99的关键.请参阅此主题.)/地板或截断,取决于标志,所以%永远不会消极):
mod.许多语言都提供了这两种语言.通常 - 如在Ada,Modula-2,一些Lisps,Haskell和Julia中 - 它们使用与modPython样式运算符和remC++样式运算符相关的名称.但并非总是如此,Fortran语言,例如,要求同样的事情modulo,并mod(如上面提到的C99).
我们不知道为什么Python,Tcl,Perl和其他有影响力的脚本语言大多选择了地板.正如问题所述,Guido van Rossum的回答只能解释为什么他必须选择三个一致答案中的一个,而不是为什么他选择了他所做的那个.
但是,我怀疑C的影响是关键.大多数脚本语言(至少最初)是用C语言实现的,并从C语言中借用它们的运算符库存.C89的实现定义%明显被破坏,不适合像Tcl或Python这样的"友好"语言.C调用运算符"mod".所以他们选择模数,而不是余数.
尽管问题在于 - 并且许多人将其用作参数-C实际上并没有与Python和朋友类似的行为.C99需要截断分割,而不是地板.C89允许,也允许任一版本的mod,因此无法保证除法属性,也无法编写可执行有符号整数除法的可移植代码.那只是打破了.
正如宝拉所说,这是因为其余部分.
该算法建立在欧几里德分部.
在Ruby中,您可以使用一致性来编写重建股息:
puts (10/3)*3 + 10%3
#=> 10
Run Code Online (Sandbox Code Playgroud)
它在现实生活中的作用相同.10个苹果和3个人.好的,你可以切三个苹果,但超出整数.
对于负数,保持一致性:
puts (-10/3)*3 + -10%3 #=> -10
puts (10/(-3))*(-3) + 10%(-3) #=> 10
puts (-10/(-3))*(-3) + -10%(-3) #=> -10
Run Code Online (Sandbox Code Playgroud)
商总是向下舍入(沿负轴向下),提醒如下:
puts (-10/3) #=> -4
puts -10%3 #=> 2
puts (10/(-3)) #=> -4
puts 10%(-3) # => -2
puts (-10/(-3)) #=> 3
puts -10%(-3) #=> -1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4663 次 |
| 最近记录: |