Почему Swift 5 String (Int) терпит неудачу, когда большое целое число более 20 цифр? - PullRequest
3 голосов
/ 11 января 2020

Я написал вышеупомянутый простой код, чтобы проверить, не содержат ли целые числа в последовательности Фибоначчи 0 или 5, и уменьшил до 1237, если целое число содержит только 1,2,3,4,6,7,8, или 9 как цифры; и если да, то затем распечатать член последовательности. Интересно, что с точки зрения числовой игры в последовательности Фибоначчи есть только 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 или около git или около нее метод String() завершается ошибкой и выдает ошибки, не выполняя проверку, потому что, согласно отладчику, целое число заменяется случайным другим целым числом полностью.

Итак, есть ли какие-либо BigInt или String обходные пути / альтернативы в Swift? Я написал Ruby код, который отлично работает в XCode, но я пытаюсь использовать исключительно Swift (и металл) для этого проекта, который в конечном итоге должен работать на iOS для коммерческих / производственных целей.

1 Ответ

3 голосов
/ 11 января 2020

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
...