Go中负整数的模数

时间:2017-03-25 15:26:47

标签: python go modulo

我目前正在学习GoLang,而且我来自Python背景。

最近,我偶然发现了%(modulo)运算符的行为,它与Python中的相应运算符不同。与modular operation和余数的定义完全相反,正整数的负整数模数返回负值。

示例:

的Python

a, b, n = -5, 5, 3
for i in range(a, b):
    print(i%n)    

输出:

1
2
0
1
2
0
1
2
0
1

开始

a, b, n := -5, 5, 3
for i:=a; i<b; i++ {
    fmt.Println(i%n)
}

输出:

-2
-1
0
-2
-1
0
1
2
0
1

在阅读Modulo operator并且很少有类似questions询问这些差异背后的原因之后,我了解这些是由于相关语言的设计目标。

Q1。我想知道为什么Go遵循C / C ++协议而不是Python。任何相关讨论的链接都会有所帮助。

Q2。 Go中是否有内置功能可以复制Python的模数运算? 备选:是否有内部方法来计算“模数”而不是“余数”?

4 个答案:

答案 0 :(得分:6)

请参阅https://gist.github.com/jianingy/5472640

  

目前的定义有几个原因:

     
      
  • %的当前语义可直接从x86架构获得
  •   
  • 更改基本运算符%的含义并且不更改其名称
  • 会令人困惑   
  • 从%result
  • 计算另一个模数相当容易   
     

请注意,%计算“余数”而不是“模数”。

标准库中没有运算符或函数复制Python的模数运算。

可以编写一个复制Python模数运算的函数:

func modLikePython(d, m int) int {
   var res int = d % m
   if ((res < 0 && m > 0) || (res > 0 && m < 0)) {
      return res + m
   }
   return res
}

请注意,Python 5 % -3中的-1||,此代码也会复制该行为。如果您不想这样,请在if语句中的int后删除第二部分。

答案 1 :(得分:1)

Python是一种特殊语言,Guido Guido van Rossum为BDFL。以下是他为什么决定与众不同的解释:

The History of Python: Why Python's Integer Division Floors

答案 2 :(得分:0)

您的第二季度

  

是否存在用于计算“模数”而不是“余数”的内部方法?

以及最前面的答案所引用的评论...

  

请注意,%计算的是“余数”,而不是“模数”。

有点误导...

查找“模”的任何定义,大体上说这是除法后的余数。问题在于,当我们说“余数”时,意味着只有一个。当涉及负数时,可以有1个以上的不同余数。在Remainder的维基百科页面上,它区分了least positive remainderleast absolute remainder。您还可以添加least negative remainder(最小负表示负,但最接近0)。

通常对于模运算符,如果返回正值,则为least positive remainder;如果返回负值,则为least negative remainder。可以多种方式确定返回值的符号。例如,给定c = a mod b,您可以将c的符号定义为

  • (Go中%的符号)
  • b的符号(%在Python中的作用)
  • 总是非负的

以下是以此https://en.wikipedia.org/wiki/Modulo_operation#In_programming_languages方式定义的编程语言及其模实现的列表。

无论如何,这是一种使用Go函数复制Python的%运算符的无分支方式

func mod(a, b int) int {
    return (a % b + b) % b
}

重申一下,这符合规则

  

给定c = a mod bc的符号将为b的符号。   换句话说,模数结果与除数的符号相同

答案 3 :(得分:0)

math/big 做欧几里得模数:

package main
import "math/big"

func mod(x, y int64) int64 {
   bx, by := big.NewInt(x), big.NewInt(y)
   return new(big.Int).Mod(bx, by).Int64()
}

func main() {
   z := mod(-5, 3)
   println(z == 1)
}

https://golang.org/pkg/math/big#Int.Mod