I can't find a right algorithm / struct to calculate the number simply in C or Go. However, a class can easily be created in Python.
At first glance, the calculation seems to be very straight forward. However, when you look at the sample calculation from Wolfram Alpha.
https://www.wolframalpha.com/input/?i=3%5E3%5E3%5E3
This breaks both long long
(integer, 18-19 digits) and double
(float / IEEE 754, up to e+308 digits, with 17 digits' precision).
However, I can cheat a little with Python, as it will automatically allocate more bytes for integer.
Still, 3^(7.625e+13) takes abnormally very long time... (3^3^3 = 7.625e+13).
import math
from decimal import Decimal
class Int:
_first = ""
_last = ""
_length = None # Int
val: int = None # actual int, if applicable
def __init__(self, val: int = 0) -> None:
if isinstance(val, Int):
if val.val is None:
self._first = val._first
self._last = val._last
self._length = val._length
return
self.val = val.val
else:
self.val = val
try:
float(self.val)
except OverflowError:
self._first = self.first
self._last = self.last
self._length = self.length
self.val = None
@property
def first(self) -> str:
if self._first:
return self._first
return str(self.val)[:8]
@property
def last(self) -> str:
if self._last:
return self._last
return str(self.val)[-8:]
@property
def length(self):
if self._length:
return self._length
return Int(len(str(self.val)))
def exp3(self):
return Int(3) ** self.val
def tetrate3(self, n: int):
first = Int(self)
for _ in range(n - 1):
first = first.exp3()
return first
def __repr__(self) -> str:
if self.val is None:
return f"{self.first}...{self.last} ({self.first[0]}.{self.first[1:]}e+{self.length})"
return f"{self.val}"
def __pow__(self, _other):
base = Int(self)
exp = Int(_other)
if base.val and exp.val:
try:
float(base.val) ** exp.val
return Int(base.val ** exp.val)
except OverflowError:
pass
log = Decimal(exp.val) * Decimal(math.log10(base.val))
fl = math.floor(float(log))
out = Int()
out._first = f"{(10 ** float(log - fl)):.7f}".replace(".", "")
out._last = str(pow(int(base.last), exp.val, 10_000_000_000))[-8:]
out._length = Int(fl)
out.val = None
return out
if __name__ == "__main__":
# After the third digits may be imprecise
# => 12579723...00739387 (1.2579723e+3638334640024)
print(Int(3).tetrate3(4))