为什么 Swift 5 字符串(Int) 在超过 20 位的大整数时失败?



我编写了上面引用的简单代码来检查斐波那契数列中的整数是否不包含 0 或 5,如果整数仅包含 1,2,3,4,6,7,8 或 9 作为数字,则减少到 1237;如果是,则打印序列的成员。有趣的是,从数字博弈的角度来看,斐波那契数列中只有 23 个这样的整数。

当整数变大时,我必须使用 Swift-BigInt 库:

func getFib1237s() {
// Some temporary variables.
var a = BInt(0)
var b = BInt(1)
var m = BInt(1)
var i = BInt(0)
var z = BInt(1)
// Get the numbers until crash...
while i < z {
let temp = a
a = b
b = b + temp
print("a: ", a)
var str = String(a)
print("String start: ", str)
str = str.replacingOccurrences(of: "9", with: "3")
print("String after 9 reducto: ", str)
str = str.replacingOccurrences(of: "6", with: "23")
print("String after 6 reducto: ", str)
str = str.replacingOccurrences(of: "8", with: "2")
print("String after 8 reducto: ", str)
str = str.replacingOccurrences(of: "4", with: "2")
print("String after 4 reducto: ", str)
if (str.firstIndex(of:"5") == nil) && (str.firstIndex(of: "0") == nil) && str.contains("1") && str.contains("2") && str.contains("3") && str.contains("7")  {
print(m, "Fib 1237 number is ", a, " | Digits: ", str.count)
m+=1
}
i+=1
z+=1
}
}

显然,在 20 位或附近,String()方法失败并抛出错误,不执行检查,因为根据调试器的说法,整数正在完全更改为随机其他整数。

那么,Swift 中是否有任何BigIntString解决方法/替代方案?我编写了在 Xcode 中运行良好的 Ruby 代码,但我试图在这个项目中专门使用 Swift(和 metal(,最终需要在 iOS 上用于商业/生产目的。

String(a)调用String.init重载,需要BinaryInteger。此初始化器很可能不是为处理超大的数字而设计的。您可以使用a.asString(radix: 10)转换为字符串。

若要使代码正常工作,还应:

  • 删除(str.firstIndex(of: "0") == nil)
  • 声明一个新的字符串变量并将替换的字符串分配给它,否则str.count将不正确。

我建议编写一个名为reduce的单独方法,因为"减少"字符串需要相当多的步骤。

这是reduce

func reduce(_ s: String) -> String {
let unique = String(Set(s))
let replaced = unique.replacingOccurrences(of: "9", with: "3")
.replacingOccurrences(of: "6", with: "23")
.replacingOccurrences(of: "8", with: "2")
.replacingOccurrences(of: "4", with: "2")
.replacingOccurrences(of: "0", with: "")
let sortedUniqueAgain = String(Set(replaced).sorted())
return sortedUniqueAgain
}

现在,我们可以检查此方法的返回值是否为 1237:

while m <= 23 {
let temp = a
a = b
b = b + temp
let str = a.asString(radix: 10)
// note that I have declared a new let constant here, instead of assigning to str
// because otherwise str.count will be wrong
let reduced = reduce(str)
if reduced == "1237"  {
print(m, "Fib 1237 number is ", a, " | Digits: ", str.count)
m+=1
}
}

输出:

1 Fib 1237 number is  317811  | Digits:  6
2 Fib 1237 number is  2178309  | Digits:  7
3 Fib 1237 number is  267914296  | Digits:  9
4 Fib 1237 number is  701408733  | Digits:  9
5 Fib 1237 number is  1134903170  | Digits:  10
6 Fib 1237 number is  72723460248141  | Digits:  14
7 Fib 1237 number is  117669030460994  | Digits:  15
8 Fib 1237 number is  8944394323791464  | Digits:  16
9 Fib 1237 number is  14472334024676221  | Digits:  17
10 Fib 1237 number is  37889062373143906  | Digits:  17
11 Fib 1237 number is  420196140727489673  | Digits:  18
12 Fib 1237 number is  1100087778366101931  | Digits:  19
13 Fib 1237 number is  1779979416004714189  | Digits:  19
14 Fib 1237 number is  2880067194370816120  | Digits:  19
15 Fib 1237 number is  19740274219868223167  | Digits:  20
16 Fib 1237 number is  83621143489848422977  | Digits:  20
17 Fib 1237 number is  927372692193078999176  | Digits:  21
18 Fib 1237 number is  781774079430987230203437  | Digits:  24
19 Fib 1237 number is  1264937032042997393488322  | Digits:  25
20 Fib 1237 number is  19134702400093278081449423917  | Digits:  29
21 Fib 1237 number is  1983924214061919432247806074196061  | Digits:  34
22 Fib 1237 number is  8404037832974134882743767626780173  | Digits:  34
23 Fib 1237 number is  162926777992448823780908130212788963731840407743629812913410  | Digits:  60

相关内容

  • 没有找到相关文章

最新更新