钟表网站开发背景文章,制作的网站,做网站 小程序前景,南宁seo咨询在我测试过的语言中#xff0c;- (x div y )不等于-x div y#xff1b; 我已经在Python中测试了//#xff0c;在Ruby中测试了/#xff0c;在Perl 6中测试了div#xff1b; C具有类似的行为。
该行为通常是按照规范进行的#xff0c;因为div通常被定义为除法结果的四舍五入…在我测试过的语言中- (x div y )不等于-x div y 我已经在Python中测试了//在Ruby中测试了/在Perl 6中测试了div C具有类似的行为。
该行为通常是按照规范进行的因为div通常被定义为除法结果的四舍五入但是从算术的角度来看这没有多大意义因为它使div在 取决于符号的不同方式这会引起混乱例如有关如何在Python中完成操作的帖子。
该设计决策背后是否有一些特定的理论依据还是只是从头开始定义div 显然Guido van Rossum在博客文章中使用了一个一致性参数该参数解释了Python的完成方式但是如果选择四舍五入您也可以具有一致性。
(受PMurias在perl6 IRC频道中提出的问题的启发)
在Python中FWIW 被称为地板分割。 试试这个.7 .1。 请注意它不会计算为int。
FWIW在Python中您可以使用双重否定来获得上限划分例如-(-23 10)
理想情况下我们希望每个b0都有两个操作div和mod满足
(a div b) * b (a mod b) a
0 (a mod b) b
(-a) div b -(a div b)
但是这在数学上是不可能的。如果以上所有条件都成立我们将有
1
21 div 2 0
1 mod 2 1
因为这是(1)和(2)的唯一整数解。因此到(3)
10 -0 -(1 div 2) (-1) div 2
由(1)表示
1-1 ((-1) div 2) * 2 ((-1) mod 2) 0 * 2 ((-1) mod 2) (-1) mod 2
制作与(2)相矛盾的(-1) mod 2 0。
因此我们需要放弃(1)(2)和(3)中的某些属性。
一些编程语言放弃(3)而将div舍入(PythonRuby)。
在某些(很少)情况下该语言提供了多个除法运算符。例如在Haskell中与Python类似div,mod仅满足(1)和(2)并且quot,rem仅满足(1)和(3)。后一对运算符将除法舍入为零以返回负余数为代价例如我们有(-1) quot 2 0和(-1) rem 2 (-1)。
C也放弃(2)并允许%返回负的余数。连贯地整数除法向零舍入。从C99开始的JavaScalaPascal和C也采用了这种策略。
C放弃了(2)。 C中的%运算符不是 mod运算符。它是余数运算符余数可以为负。
EricLippert出于好奇如果是这种情况为什么操作员ID字符串为op_Modulus而不是op_Remainder
Heinzi我没有确定的充分理由。这只是很长的小错误列表中的一个这些小错误并不重要。
只需将方程式的两边都除以零
浮点运算是由IEEE754定义的并考虑了数字应用程序默认情况下以非常严格定义的方式舍入到最接近的可表示值。
通用国际标准未定义计算机中的整数运算。语言(尤其是C家族的语言)授予的操作倾向于遵循基础计算机提供的任何内容。某些语言比某些语言更健壮地定义某些操作但是为了避免在当时可用(和流行)的计算机上实现过于困难或缓慢的实现它们会选择一种非常接近其行为的定义。
因此整数运算倾向于在溢出时回绕(用于加法乘法和左移)并且在产生不精确的结果时(用于除法和右移)会向负无穷大舍入。在二进制补码二进制算术中这两个都是在整数各自的结尾处的简单截断处理极端情况的最简单方法。
其他答案则讨论了语言与除法运算可能提供的余数或模运算符之间的关系。不幸的是他们倒退了。余数取决于除法的定义而不是相反的定义而模数可以独立于除法定义-如果两个参数碰巧都是正数且除法向下取整则它们的结果相同因此人们很少注意到。
大多数现代语言都提供余数运算符或模数运算符很少会同时提供。库函数可以为关心差异的人们提供其他操作即余数保留除数的符号而模数保留除数的符号。
这是一个有趣的观点也因为您是指模块化算术。如果问题是为什么整数除法会在许多脚本语言中取整您是否认为相同的答案可能适用
iGian好吧事实是由于我在答案中概述的原因大多数语言都无法进行整数除法。通常他们要么调用CPU DIV指令并只接受它的功能要么调用实现欧几里得除法的子例程并且通常执行相同的操作。一个合理的问题可能是为什么在大多数其他语言都没有的情况下语言X会四舍五入(或趋近于零或趋近于零) -但您必须指定X答案将特定于该语言。
那么许多脚本语言会舍入整数除法因为CPU DIV基本上是欧几里得除法的实现 ----我很好奇为什么需要四舍五入。您能推荐一种语言X吗
iGian就是这样我不知道一个副手-您是提出它的人。除非另有明确说明否则有几种方法会默默地将整数操作数强制转换为浮点并执行浮点除法。例如。 BBC BASIC将定义为FP div将DIV定义为带舍入的整数。 6502甚至没有DIV指令因此带有子程序。
在C和C 和Java中除法向零截断向右移向负无穷大。
如何处理负无穷大是处理极端情况的最简单方法为什么不趋向于零或正无穷大或下一个整数GOTO0我的答案就在那二进制截断补码算术。具有除法指令的现代CPU通常会这样做许多软件子例程也会这样做。但是在子例程中实现它的一种方法是对操作数的正形式执行无符号除法然后再固定符号。将趋近于零。
事实并非如此整数除法根本不涉及截断(在所有中间步骤中仅计算整数值)。同样在x86和类似体系结构上整数除法指令始终四舍五入为零。GOTO0向零舍入模式的名称是截断。例如浮点trunc()函数en.cppreference.com/w/c/numeric/math/trunc。如果将整数除法视为产生实数的数学除法然后将其四舍五入为整数则舍入舍入模式将表示该行为。当然那不是其在内部实际实施的方式。 BTW对于算术右移向-Inf显然是2s补码中最简单的您只需移入符号位的副本即可得到。
但是这个答案有一个错误。在大多数语言/ ISA中似乎声称整数除法通常会向-Inf取整。那对于所有具有除法指令的现代CPU体系结构都是不正确的对于ISO C99和ISO C 11也是不正确的它们都精确地指定了有符号整数除法舍入语义(以匹配所有现代CPU的功能)。在C 中使用负数进行整数除法舍入。先前的修订版将其留给实现来选择一种行为(以提高使用不同语义的硬件的效率)。
PeterCordes实际上截断仅描述符号幅度表示(例如IEEE-754浮点)中的舍入为零。在二进制补码表示法中截断实际上是朝着负无穷大舍入这就是从最有意义的一端转移符号位副本的简单权宜之计。特别是如果0xFFFF为-1则0xFFFE为-2。
Chromatix啊我明白了这个术语的意义。但是我的意思是数学截断(en.wikipedia.org/wiki/Truncation)即截断是指将小数点(或二进制)点后的某些位置截断或者将小数部分去除/归零。截断是数学中的一个术语不仅仅是计算机科学/工程学其含义是向零舍入。我认为不管实现如何都将舍入为零是最有意义的。 (即使这意味着您不能简单地截断2s补码表示的位。)
Wikipedia在这方面有很棒的文章包括历史和理论。
只要语言满足(a/b) * b (a%b) a的欧几里得除法属性则地板除法和截断除法都是连贯且在算术上有意义的。
当然人们喜欢争辩说一个显然是正确的而另一个显然是错误的但它比起明智的讨论更具有圣战的性质并且通常更多地与选择他们的早期首选语言有关。其他。他们通常也倾向于主要为他们选择的%争论尽管先选择/然后选择匹配的%可能更有意义。
地板(如Python)
就像唐纳德·克努斯(Donald Knuth)所建议的那样。
%跟随除数的符号显然是大约70的学生猜测
通常将运算符读取为mod或modulo而不是remainder。C做到了 —甚至都不是事实。1
截断(如C )
使整数除法与IEEE浮点除法更加一致(在默认的四舍五入模式下)。
更多的CPU实现了它。 (在历史的不同时期可能并非如此。)
运算符被读取为modulo而不是remainder(即使这实际上与他们的观点背道而驰)。
从概念上讲除法属性更多地是关于余数而不是模量。
运算符被读取为mod而不是modulo因此应遵循Fortran的区分。 (这听起来很愚蠢但可能是C99的关键所在。请参阅此线程。)
欧几里得(如Pascal- /底数或根据符号截断因此%永远不会为负)
尼克劳斯·沃思(Niklaus Wirth)认为没有人对肯定的mod感到惊讶。
雷蒙德·布特(Raymond T. Boute)后来提出您不能凭借其他任何一条规则天真地实现欧几里得除法。
多种语言都提供。通常与AdaModula-2一些LispsHaskell和Julia一样它们使用与mod有关的名称(对于Python风格的运算符)和与rem有关的名称对于C 风格的运算符。但并非总是如此-例如Fortran调用相同的内容modulo和mod(如上面C99所述)。
我们不知道为什么PythonTclPerl和其他有影响力的脚本语言大多选择地板。正如问题中提到的Guido van Rossum的答案仅说明了为什么他必须选择三个一致的答案之一而不是为什么他选择了自己选择的答案。
但是我怀疑C的影响是关键。大多数脚本语言(至少在最初是用C语言实现的)并从C语言借用其操作员清单。C89的实现定义的%显然已损坏不适合Tcl或Python之类的友好语言。 C将运算符称为 mod。因此它们采用模数而不是余数。
1。尽管问题说了什么(很多人都使用它作为参数)但C的行为实际上与Python和其朋友并不相似。 C99需要截断分割而不是分割。 C89允许使用任一版本也允许使用任一版本的mod因此无法保证除法属性也无法编写具有符号整数除法的可移植代码。真是坏了。 sub
一些LispsCommon Lisp定义了mod和rem请参见lispworks.com/documentation/HyperSpec/Body/f_mod_r.htm和lispworks.com/documentation/HyperSpec/Body/f_floorc.htm
coredump和其他一些Lisps使用其他名称。 MacLisp只提供了一个而Racket今天也做同样的事情。 Scheme提供了三个(moduloremainder,和Wirth样式的mod)。我认为答案不需要与世界上每种语言的方言相关联说某些Lips使用mod / rem样式命名似乎足够了。
因为整数除法的含义是完整答案包括余数。
...而根据定义其余部分必须始终为正显然并非每种语言都适用在C99中其余符号与红利符号相同
是的这是正确的评论的下限使我发疯
jjmerelo在Python中其余部分(使用%或divmod())始终与除数具有相同的符号。例如123 % -10- -7SeanFrancisN.Ballais显然只是个惯例问题。维基百科关于模运算的条目说当a或n为负数时天真定义会失效并且编程语言会在定义这些值的方式上有所不同。
正如宝拉(Paula)所说这是由于剩余的原因。
该算法基于欧几里得除法。
在Ruby中您可以编写以下代码来重建一致性
1
2puts (10/3)*3 10%3
# 10
它在现实生活中的作用相同。 10个苹果和3个人。好的您可以将苹果切成三等分但要超出设定的整数。
使用负数时也保持一致性
1
2
3puts (-10/3)*3 -10%3 # -10
puts (10/(-3))*(-3) 10%(-3) # 10
puts (-10/(-3))*(-3) -10%(-3) # -10
商总是向下取整(沿负轴向下)并且提示如下
1
2
3
4
5
6
7
8puts (-10/3) # -4
puts -10%3 # 2
puts (10/(-3)) # -4
puts 10%(-3) # -2
puts (-10/(-3)) # 3
puts -10%(-3) # -1
因此除法和模运算必须是连贯的这很清楚。但是您可以选择向上或向下取整只要这些等式成立就可以保持连贯性。
jjmerelo我同意你的看法在数学上您可以选择其他规则其中# 10 3 4 # 10 % 3 -2 # 3 * 4 - 2 10。但这不适用于-2不存在的自然数集。
iGian您缺少的答案是有多种方法可以保持负数的一致性而不更改正数的结果。