这段话是否正确?「取余这个运算,只有 Python 是对的。当初 C 这个老师教错了,那么一大票学生也就只敢跟着老师错。只有 Python 敢于站出来坚持正确答案。」

18 小时 46 分钟前
 cnbatch

今天在看一篇公众号文章《性能之王:最快的编程语言》,发现评论区有这么一段对话:

然后我找了下在 stackexchange 的真实提问:

https://math.stackexchange.com/questions/623449/negative-number-divided-by-positive-number-what-would-be-remainder

从回答来看,C 和 Python 的两种做法在数值计算上都是成立的。两种做法的区别在于是否允许余数为负数,或者说,符号该不该与原数值相同。

不允许余数出现负数的,是目前广泛使用的欧几里得除法。

所以“数学洁癖”会认为负值余数是错的?

3086 次点击
所在节点    C
46 条回复
favourstreet
10 小时 24 分钟前
兄弟们,还是看一看实部或者虚部有一个是浮点数∞的时候都复数乘法该怎么算吧,我支持单点紧化
NessajCN
9 小时 12 分钟前
定义问题
数学上你 7%3 == -2 也是对的,也就是个向左取还是向右取的选择
FishBear
9 小时 7 分钟前
@liprais #9 冒犯了哦.
laikick
8 小时 51 分钟前
无所谓 PHP 会出手
edwardzcn98
8 小时 9 分钟前
应该只是定义不同,无关对错,哪里来的 python 精神可敬。。以下是 Lean 中求余的表达,官方也解释早期用 truncation-rounding 定义,后来用的 euclidean 定义。表达数学能力有差别,所以才改。

这篇文章解释了几种定义下的除法和求余
https://dl.acm.org/doi/pdf/10.1145/128861.128862

```lean4
-- default (guess using emod as default)
#eval (-1: Int) % (3: Int) -- 2
#eval (1: Int) % (-3: Int) -- 1

-- using emod (euclidean division)
#eval (-1: Int).emod (3 : Int) -- 2
#eval (1: Int).emod (-3 : Int) -- 1

-- using tmod (truncating division)
#eval (-1 : Int).tmod (3 : Int) -- -1
#eval (-1 : Int).tmod (-3 : Int) -- -1
```
edwardzcn98
7 小时 53 分钟前
这个算是标答了。以及#19 提到了同样一篇文章
edwardzcn98
7 小时 52 分钟前
edwardzcn98
7 小时 52 分钟前
指#20 @geelaw
paopjian
7 小时 38 分钟前
这种拉一捧一的不是来秀优越性的么,计算机领域尊重数学某一学派就叫对,不遵守就叫错? 那看来编程语言有精度问题就可以说不配存在了
mengdodo
7 小时 37 分钟前
@laikick 你真是个天才
geelaw
7 小时 36 分钟前
@geelaw #20 修正,数论常见的带余除法应该是 1 = 0*(-3) + 1
cybort
6 小时 26 分钟前
这个是和取整方法有关的,C 语言取的是向 0 取整的结果,你给出来的是向下取整的结果。如果-1/3+1/3 不等于 0 ,其实更反直觉。运算系统本来就是人为定义的,欧氏空间也不比其他空间跟高贵,关键是哪一种好用。
Maboroshii
6 小时 21 分钟前
说起来可能有点可笑,我长这么大还没用过负数取模...
xuld
6 小时 13 分钟前
并不是其他语言是错的,而是其他语言管 % 叫取模运算,这些语言规范中从没说 % 是取余运算。只不过取模运算在正数的时候,结果和取余是相同的。
xuanbg
5 小时 47 分钟前
我个人不太认可数学洁癖的说法,我认为除法向零取整才是符合直觉的。所以 C 的做法没错,Python 反倒是有点矫情了
realpg
5 小时 0 分钟前
InkStone
4 小时 23 分钟前
欧几里得除法是什么玩意儿,你是想说辗转相除法么?这只是一个算法而已,不是什么取模的定义。

事实上你在正经的数学文献里几乎不会看到取模运算这种东西,只有同余恒等式,没有取模运算。这跟编程里的概念是不一样的。

什么是同余恒等式? 7 ≡ 17 ( mod 10 ),这才是数学的东西。
NoOneNoBody
4 小时 20 分钟前
一个是整除后,跟整除结果的距离。这里还有整除定义的问题,是除法结果的整数部分,还是除法结果向较小方向取整
一个是分段区间跟较小端的距离 # 这个才叫“余下”,其实在负数情况下,人类语义基本就没有“余下”概念了,而是叫“尚缺”,就是和分段区间较大端的距离
数学是脱离文字语言,对数字计算的归一处理,即使负数,也按相同的准则定义和计算。其中欧氏除法统一和较小端比较,或者说整除是除法结果取不大于该结果的最大整数

编程是定义整除为“除法结果的整数部分”,取模为“跟整除结果倍数的距离”,其中余数符号的意义是方向
它未必要向人类语义看齐,例如计数器下标从 0 开始,是不吻合人类理解的,就像公元一世纪,就是 01-100 年,没有公元零年或公元零世纪,想当年 1999~2000 跨年夜,一堆人庆祝“进入新世纪”就很好笑

所以,计算机求“余”的计算,要按实际需求重写算法,而不是单纯用某个表达式替代
GuuJiang
3 小时 52 分钟前
@InkStone 不了解的东西可以先去检索而不是直接断言,欧几里得除法是个专有概念,维基百科都能查到,另外 rust 语言里的各种数值类型都提供了内置的 div_euclid 和 rem_euclid 方法
moxuze
3 小时 40 分钟前
数组这个下标,只有 Lua 是对的。当初 Python 这个老师教错了,那么一大票学生也就只敢跟着老师错。只有 Lua 敢于站出来坚持正确答案。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1093235

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX