import strutils const BASE = 1_000_000_000'u64 const BASE_DIGITS = 9 type BigInt* = object sign*: int # -1, 0, 1 digits*: seq[uint32] # little endian limbs proc normalize(a: var BigInt) = while a.digits.len > 0 and a.digits[^1] == 0: a.digits.setLen(a.digits.len - 1) if a.digits.len == 0: a.sign = 0 elif a.sign == 0: a.sign = 1 proc big*(x: int): BigInt = if x == 0: return BigInt(sign: 0) var v = abs(x) result.sign = if x < 0: -1 else: 1 while v > 0: result.digits.add(uint32(v mod int(BASE))) v = v div int(BASE) proc parse*(s: string): BigInt = var str = s result.sign = 1 if str[0] == '-': result.sign = -1 str = str[1..^1] for i in countdown(str.len, 1, BASE_DIGITS): let start = max(0, i - BASE_DIGITS) let chunk = parseInt(str[start.. 0: result.digits.add(uint32(carry)) result.sign = 1 result.normalize() proc sub(a, b: BigInt): BigInt = var borrow: int64 = 0 result.digits = newSeq[uint32](a.digits.len) for i in 0.. 0: result = sub(a, b) result.sign = a.sign else: result = sub(b, a) result.sign = b.sign proc `-`*(a, b: BigInt): BigInt = var nb = b nb.sign *= -1 a + nb proc `*`*(a, b: BigInt): BigInt = if a.sign == 0 or b.sign == 0: return BigInt(sign: 0) result.digits = newSeq[uint32](a.digits.len + b.digits.len) for i in 0.. 0: let cur = uint64(result.digits[pos]) + carry result.digits[pos] = uint32(cur mod BASE) carry = cur div BASE inc pos result.sign = a.sign * b.sign result.normalize() proc `$`*(a: BigInt): string = if a.sign == 0: return "0" var parts: seq[string] for d in a.digits: parts.add($d) result = parts[^1] for i in countdown(parts.len - 2, 0): result.add(parts[i].align(BASE_DIGITS, '0')) if a.sign < 0: result = "-" & result when isMainModule: let a = parse("123456789123456789123456789") let b = parse("987654321987654321987654321") echo "a = ", a echo "b = ", b echo "a + b = ", a + b echo "a * b = ", a * b