如何让 Scala 处理大数
How to get Scala to handle large numbers
我在 Python 中有一个函数,我正在尝试将其转换为 Scala:
Python:
def pseudoRandom(value):
loops = (value & 0x7F) + 21
for index in range(loops):
value += ((value * 7) ^ (value << 15)) + 8 * index - (value >> 5)
value &= ((1 << 64) - 1)
return value
在Scala中我定义如下:
def pseudoRandom(value: Long): Long = {
val loops = (value & 0x7F) + 21L
var v = value
(0L to loops).foreach { index =>
v += ((v * 7) ^ (v << 15)) + 8 * index - (v >> 5)
v &= ((1 << 64) -1)
}
v
}
这可能是由于溢出而失败,但我不确定如何修复它。我试过按如下方式使用 BigInt:
def pseudoRandom(value: Long): BigInt = {
val loops = (value & 0x7F) + 21L
var v = BigInt(value)
(0L to loops).foreach { index =>
v += ((v * 7) ^ (v << 15)) + 8 * index - (v >> 5)
v &= ((1 << 64) -1)
}
v
}
这也失败了。
我期望的行为(基于 python 代码):
Input Output
1 7979149037415411353
2 934307080801911839
3 9329215801069440317
我的 scala 代码的实际输出
Input Output
1 0
2 0
3 0
这个有效:
def pseudoRandom(value: Long): BigInt = {
val loops = (value & 0x7F).toInt + 21
val mask = (BigInt(1) << 64) - 1
var v = BigInt(value)
for (i <- 0 until loops) {
v += ((v * 7) ^ (v << 15)) + 8 * i - (v >> 5)
v &= mask
}
v
}
您的代码问题的未排序枚举:
- 一截断到
& 0x7F
,肯定是small int,不是long
range(n)
对应0 until n
,不是0 to n
1 << 64
不会给你任何理智,而是定义一次 BigInt
掩码
foreach
是 non-idiomatic,为此使用简单的 for
-循环糖。
前十个正整数的输出:
7979149037415411353
934307080801911839
9329215801069440317
8332103895783241284
1972840215733196111
9936661750801020912
9568736274889204650
13195389261695658308
3299225817465251241
3456601764545139813
出现零是因为 (1 << 64) - 1 = 0
我在 Python 中有一个函数,我正在尝试将其转换为 Scala:
Python:
def pseudoRandom(value):
loops = (value & 0x7F) + 21
for index in range(loops):
value += ((value * 7) ^ (value << 15)) + 8 * index - (value >> 5)
value &= ((1 << 64) - 1)
return value
在Scala中我定义如下:
def pseudoRandom(value: Long): Long = {
val loops = (value & 0x7F) + 21L
var v = value
(0L to loops).foreach { index =>
v += ((v * 7) ^ (v << 15)) + 8 * index - (v >> 5)
v &= ((1 << 64) -1)
}
v
}
这可能是由于溢出而失败,但我不确定如何修复它。我试过按如下方式使用 BigInt:
def pseudoRandom(value: Long): BigInt = {
val loops = (value & 0x7F) + 21L
var v = BigInt(value)
(0L to loops).foreach { index =>
v += ((v * 7) ^ (v << 15)) + 8 * index - (v >> 5)
v &= ((1 << 64) -1)
}
v
}
这也失败了。
我期望的行为(基于 python 代码):
Input Output
1 7979149037415411353
2 934307080801911839
3 9329215801069440317
我的 scala 代码的实际输出
Input Output
1 0
2 0
3 0
这个有效:
def pseudoRandom(value: Long): BigInt = {
val loops = (value & 0x7F).toInt + 21
val mask = (BigInt(1) << 64) - 1
var v = BigInt(value)
for (i <- 0 until loops) {
v += ((v * 7) ^ (v << 15)) + 8 * i - (v >> 5)
v &= mask
}
v
}
您的代码问题的未排序枚举:
- 一截断到
& 0x7F
,肯定是small int,不是long range(n)
对应0 until n
,不是0 to n
1 << 64
不会给你任何理智,而是定义一次BigInt
掩码foreach
是 non-idiomatic,为此使用简单的for
-循环糖。
前十个正整数的输出:
7979149037415411353
934307080801911839
9329215801069440317
8332103895783241284
1972840215733196111
9936661750801020912
9568736274889204650
13195389261695658308
3299225817465251241
3456601764545139813
出现零是因为 (1 << 64) - 1 = 0