BigIntプロジェクトの中核である BigInt.swift にバグがあったので修正版を載せます。テキストエディタにコピペしてファイル名を必ずBigInt.swift または BigInt.swift.rtf(テキストファイル)で保存してください。

 

import Foundation

 

public struct BigInt: Comparable, ExpressibleByStringLiteral, ExpressibleByIntegerLiteral {

    public var digits: [UInt8]

    public var isNegative: Bool

 

    public init(_ number: String) {

        var str = number.trimmingCharacters(in: CharacterSet.whitespaces)

 

        if str.hasPrefix("-") {

            isNegative = true

            str.removeFirst()

        } else {

            isNegative = false

        }

 

        let dropped = str.drop(while: { $0 == "0" })

        str = dropped.isEmpty ? "0" : String(dropped)

 

        if str.allSatisfy({ $0.isNumber }) {

            digits = str.reversed().compactMap { UInt8(String($0)) }

        } else {

            fatalError("Invalid characters in BigInt initializer: \(number)")

        }

 

        if digits == [0] {

            isNegative = false

        }

    }

 

    public init(stringLiteral value: String) {

        self.init(value)

    }

 

    public init(integerLiteral value: Int) {

        self.init(String(value))

    }

 

    public static func == (lhs: BigInt, rhs: BigInt) -> Bool {

        lhs.isNegative == rhs.isNegative && lhs.digits == rhs.digits

    }

 

    public static func < (lhs: BigInt, rhs: BigInt) -> Bool {

        if lhs.isNegative != rhs.isNegative {

            return lhs.isNegative

        }

 

        if lhs.digits.count != rhs.digits.count {

            return lhs.isNegative ? lhs.digits.count > rhs.digits.count : lhs.digits.count < rhs.digits.count

        }

 

        for (l, r) in zip(lhs.digits.reversed(), rhs.digits.reversed()) {

            if l != r {

                return lhs.isNegative ? l > r : l < r

            }

        }

        return false

    }

 

    public static func + (lhs: BigInt, rhs: BigInt) -> BigInt {

        if lhs.isNegative == rhs.isNegative {

            let result = add(lhs.digits, rhs.digits)

            return BigInt(digits: result, isNegative: lhs.isNegative).trimmed()

        } else {

            if abs(lhs) >= abs(rhs) {

                let result = subtract(lhs.digits, rhs.digits)

                return BigInt(digits: result, isNegative: lhs.isNegative).trimmed()

            } else {

                let result = subtract(rhs.digits, lhs.digits)

                return BigInt(digits: result, isNegative: rhs.isNegative).trimmed()

            }

        }

    }

 

    public static func * (lhs: BigInt, rhs: BigInt) -> BigInt {

        let result = multiply(lhs.digits, rhs.digits)

        return BigInt(digits: result, isNegative: lhs.isNegative != rhs.isNegative).trimmed()

    }

 

    private static func add(_ a: [UInt8], _ b: [UInt8]) -> [UInt8] {

        let maxLength = max(a.count, b.count)

        var result: [UInt8] = []

        var carry: UInt8 = 0

        for i in 0..<maxLength {

            let digitA = i < a.count ? a[i] : 0

            let digitB = i < b.count ? b[i] : 0

            let sum = digitA + digitB + carry

            result.append(sum % 10)

            carry = sum / 10

        }

        if carry > 0 { result.append(carry) }

        return result

    }

 

    private static func subtract(_ a: [UInt8], _ b: [UInt8]) -> [UInt8] {

        var result: [UInt8] = []

        var borrow: Int = 0

        for i in 0..<a.count {

            let digitA = Int(a[i])

            let digitB = i < b.count ? Int(b[i]) : 0

            var sub = digitA - digitB - borrow

            if sub < 0 {

                sub += 10

                borrow = 1

            } else {

                borrow = 0

            }

            result.append(UInt8(sub))

        }

        return result

    }

 

    private static func multiply(_ a: [UInt8], _ b: [UInt8]) -> [UInt8] {

        var result = [UInt8](repeating: 0, count: a.count + b.count)

        for i in 0..<a.count {

            var carry: UInt16 = 0

            for j in 0..<b.count {

                let mul = UInt16(a[i]) * UInt16(b[j]) + UInt16(result[i + j]) + carry

                result[i + j] = UInt8(mul % 10)

                carry = mul / 10

            }

            result[i + b.count] += UInt8(carry)

        }

        return result

    }

 

    private func trimmed() -> BigInt {

        var copy = self

        while copy.digits.count > 1 && copy.digits.last == 0 {

            copy.digits.removeLast()

        }

        if copy.digits == [0] { copy.isNegative = false }

        return copy

    }

 

    public init(digits: [UInt8], isNegative: Bool) {

        self.digits = digits

        self.isNegative = isNegative

    }

 

    public static prefix func - (value: BigInt) -> BigInt {

        if value == BigInt("0") { return value }

        return BigInt(digits: value.digits, isNegative: !value.isNegative)

    }

}

 

extension BigInt {

    public static func abs(_ value: BigInt) -> BigInt {

        return BigInt(digits: value.digits, isNegative: false)

    }

}

 

extension BigInt: CustomStringConvertible {

    public var description: String {

        let numberString = digits.reversed().map(String.init).joined()

        return isNegative && numberString != "0" ? "-" + numberString : numberString

    }

}