Go 中负整数的模

问题描述 投票:0回答:5

我正在学习 Go,并且我有 Python 背景。

最近,我偶然发现了

%
(模)运算符的行为,它与 Python 中相应的运算符不同。与模运算和余数的定义完全相反,负整数与正整数的模返回负值。

示例:

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

在阅读了模运算符和一些类似的问题询问这些差异背后的原因后,我了解到这些差异是由于相关语言的设计目标造成的。

Go 中是否有内置功能可以复制 Python 的模数运算?

替代:是否有一种内部方法来计算“模数”而不是“余数”?

go modulo
5个回答
19
投票

参见 一位语言设计者的评论

目前的定义有几个原因:

  • 由于 x86 架构,% 的当前语义可直接使用
  • 改变初等运算符 % 的含义而不改变其名称会令人困惑
  • 从 % 结果计算另一个模数是相当容易的

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

标准库中没有复制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
之后的第二部分。


17
投票

如果您想要一个实现 Python 求模行为的 Go 函数,请尝试以下操作:

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

如果您想了解模数与余数的解释,请继续阅读。

几乎所有模数的定义都是除法后的余数。换句话说,模与余数是错误的二分法,因为它们是同一件事。

之所以出现区别,是因为定义余数的合理方法不止一种,不同的定义会给出不同的结果。

例如,考虑 11 除以 5,真商为 2.2。在整数的上下文中,有不止一种方法可以解释这一点:

  • 2 的商和 1 的余数
  • 3 的商和 -4 的余数

对于负 11 除以 5:

  • -2 的商和-1 的余数
  • -3 的商和 4 的余数

有几种方法可以指定我们想要的余数。例如,通过选择如何舍入真商来找到整数商(向上舍入、向下舍入、向零舍入)。也许最简单的方法是选择我们希望余数具有什么符号(当它非零时)。例如,我们可以说余数

a mod b
应该与
a
具有相同的符号。这就是 Go 的
%
运算符的工作原理。您也可以说余数
a mod b
应该与
b
具有相同的符号。这就是 Python 的
%
运算符的工作原理。

维基百科对一些模的各种定义进行了细分,以及按其使用的定义标记的编程语言列表


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


0
投票

在第二季度,您可以使用:

func modNeg(v, m int) int {
    return (v%m + m) % m
}

会输出:

modNeg(-1, 5) => 4
modNeg(-2, 3) => 0

0
投票

在大多数情况下,只需将第二个数字添加到结果中即可:

Python:

-8%6 => 4

戈兰:

-8%6 + 6 => 4

所以函数会是这样的:

func PyMod(d int, m int) int {
  d %= m
  if d < 0 { 
    d += m
  }
  return d
}

除了

a%-b
之外,它还适用于其他一些情况,例如
-a%b

但是如果你想让它对

-a%-b
也起作用,请这样做:

func PyMod(d int, m int) int {
  // Add this condition at the top
  if d < 0 && m < 0 {
    return d % m
  } 
  d %= m
  if d < 0 { 
    d += m
  }
  return d
}
© www.soinside.com 2019 - 2024. All rights reserved.