Displaying abbreviated numbers over 9.223Qi

Alright so I need quite a bit of help,

I have this script here that has never failed me before, up until I added abbreviations above Qi


local player = game.Players.LocalPlayer

player.Coins.Changed:Connect(function()
	local abbrev = {"", "K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", 'Oc', "N", "D", "Ud", "Dd", "Td", 'Qt', "Qd", "Sd", "St", "Od", "Nod", "V", "Cv"}

	local function Format(value, idp)
		print(math.log(math.max(1, math.abs(value)), 1000))
		local ex = math.floor (math.log(math.max(1, math.abs(value)), 1000))
		print(ex)
		local abbrevs = abbrev [1 + ex] or ("e+"..ex)
		print(abbrevs)
		local normal = math.floor (value * ((10 ^ idp) / (1000 ^ ex))) / (10 ^ idp)

		return ("%."..idp.."f%s"):format(normal, abbrevs)
	end

	if player:WaitForChild("Coins").Value >= 1000 then
		script.Parent.Text = "Coins: "..Format(player:WaitForChild("Coins").Value)
	else
		script.Parent.Text = "Coins: "..player:WaitForChild("Coins").Value
	end
end)

At first I was very confused, trying to figure out why it wouldn’t go past 9.223Qi, but then I remembered that a while back I read an article on the DevForum about strings being capped off at 13 digits, and I honestly have no idea how to fix this, I know it for sure can be done because games like SPTS, Ninja Legends, and tons of other simulators have numbers pass Qi.

Any help is MUCH APPRECIATED

-TSL

It seems like you’re hitting the number cap (as shown on this page), you’d probably have to use some form of BigNum such as this one, as it allows you to go over 2^63-1:

Link

You’ll definitely have to modify it however, since it’s not written for Roblox and uses things like io.write. However, it’s fairly trivial and I completed it fairly quickly.
Modified:

--!nocheck

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{1
--
--  File Name:              bignum.lua
--  Package Name:           BigNum 
--
--  Project:    Big Numbers library for Lua
--  Mantainers: fmp - Frederico Macedo Pessoa
--              msm - Marco Serpa Molinaro
--
--  History:
--     Version      Autor       Date            Notes
--      1.1      fmp/msm    12/11/2004   Some bug fixes (thanks Isaac Gouy)
--      alfa     fmp/msm    03/22/2003   Start of Development
--      beta     fmp/msm    07/11/2003   Release
--
--  Description:
--    Big numbers manipulation library for Lua.
--    A Big Number is a table with as many numbers as necessary to represent
--       its value in base 'RADIX'. It has a field 'len' containing the num-
--       ber of such numbers and a field 'signal' that may assume the values
--       '+' and '-'.
--
-- Modified for use in Roblox
---$.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


--%%%%%%%%  Constants used in the file %%%%%%%%--{{{1
RADIX = 10^7 ;
RADIX_LEN = math.floor( math.log10 ( RADIX ) ) ;


--%%%%%%%%        Start of Code        %%%%%%%%--

BigNum = {} ;
BigNum.mt = {} ;


--BigNum.new{{{1
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
--
--  Function: New 
--
--
--  Description:
--     Creates a new Big Number based on the parameter num.
--
--  Parameters:
--     num - a string, number or BigNumber.
--
--  Returns:
--     A Big Number, or a nil value if an error occured.
--
--
--  %%%%%%%% --

function BigNum.new( num ) --{{{2
	local bignum = {} ;
	setmetatable( bignum , BigNum.mt ) ;
	BigNum.change( bignum , num ) ;
	return bignum ;
end

--%%%%%%%%%%%%%%%%%%%% Functions for metatable %%%%%%%%%%%%%%%%%%%%--{{{1
--BigNum.mt.sub{{{2
function BigNum.mt.sub( num1 , num2 )
	local temp = BigNum.new() ;
	local bnum1 = BigNum.new( num1 ) ;
	local bnum2 = BigNum.new( num2 ) ;
	BigNum.sub( bnum1 , bnum2 , temp ) ;
	return temp ;
end

--BigNum.mt.add{{{2
function BigNum.mt.add( num1 , num2 )
	local temp = BigNum.new() ;
	local bnum1 = BigNum.new( num1 ) ;
	local bnum2 = BigNum.new( num2 ) ;
	BigNum.add( bnum1 , bnum2 , temp ) ;
	return temp ;
end

--BigNum.mt.mul{{{2
function BigNum.mt.mul( num1 , num2 )
	local temp = BigNum.new() ;
	local bnum1 = BigNum.new( num1 ) ;
	local bnum2 = BigNum.new( num2 ) ;
	BigNum.mul( bnum1 , bnum2 , temp ) ;
	return temp ;
end

--BigNum.mt.div{{{2
function BigNum.mt.div( num1 , num2 )
	local bnum1 = {} ;
	local bnum2 = {} ;
	local bnum3 = BigNum.new() ;
	local bnum4 = BigNum.new() ;
	bnum1 = BigNum.new( num1 ) ;
	bnum2 = BigNum.new( num2 ) ;
	BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
	return bnum3 , bnum4 ;
end

--BigNum.mt.tostring{{{2
function BigNum.mt.tostring( bnum )
	local i = 0 ;
	local j = 0 ;
	local str = "" ;
	local temp = "" ;
	if bnum == nil then
		return "nil" ;
	elseif bnum.len > 0 then
		for i = bnum.len - 2 , 0 , -1  do
			for j = 0 , RADIX_LEN - string.len( bnum[i] ) - 1 do
				temp = temp .. '0' ;
			end
			temp = temp .. bnum[i] ;
		end
		temp = bnum[bnum.len - 1] .. temp ;
		if bnum.signal == '-' then
			temp = bnum.signal .. temp ;
		end
		return temp ;
	else
		return "" ;
	end
end

--BigNum.mt.pow{{{2
function BigNum.mt.pow( num1 , num2 )
	local bnum1 = BigNum.new( num1 ) ;
	local bnum2 = BigNum.new( num2 ) ;
	return BigNum.pow( bnum1 , bnum2 ) ;
end

--BigNum.mt.eq{{{2
function BigNum.mt.eq( num1 , num2 )
	local bnum1 = BigNum.new( num1 ) ;
	local bnum2 = BigNum.new( num2 ) ;
	return BigNum.eq( bnum1 , bnum2 ) ;
end

--BigNum.mt.lt{{{2
function BigNum.mt.lt( num1 , num2 )
	local bnum1 = BigNum.new( num1 ) ;
	local bnum2 = BigNum.new( num2 ) ;
	return BigNum.lt( bnum1 , bnum2 ) ;
end

--BigNum.mt.le{{{2
function BigNum.mt.le( num1 , num2 )
	local bnum1 = BigNum.new( num1 ) ;
	local bnum2 = BigNum.new( num2 ) ;
	return BigNum.le( bnum1 , bnum2 ) ;
end

--BigNum.mt.unm{{{2
function BigNum.mt.unm( num )
	local ret = BigNum.new( num )
	if ret.signal == '+' then
		ret.signal = '-'
	else
		ret.signal = '+'
	end
	return ret
end

--%%%%%%%%%%%%%%%%%%%% Metatable Definitions %%%%%%%%%%%%%%%%%%%%--{{{1

BigNum.mt.__metatable = "hidden"           ; -- answer to getmetatable(aBignum)
-- BigNum.mt.__index     = "inexistent field" ; -- attempt to acess nil valued field 
-- BigNum.mt.__newindex  = "not available"    ; -- attempt to create new field
BigNum.mt.__tostring  = BigNum.mt.tostring ;
-- arithmetics
BigNum.mt.__add = BigNum.mt.add ;
BigNum.mt.__sub = BigNum.mt.sub ;
BigNum.mt.__mul = BigNum.mt.mul ;
BigNum.mt.__div = BigNum.mt.div ;
BigNum.mt.__pow = BigNum.mt.pow ;
BigNum.mt.__unm = BigNum.mt.unm ;
-- Comparisons
BigNum.mt.__eq = BigNum.mt.eq   ; 
BigNum.mt.__le = BigNum.mt.le   ;
BigNum.mt.__lt = BigNum.mt.lt   ;
--concatenation
-- BigNum.me.__concat = ???

setmetatable( BigNum.mt, { __index = "inexistent field", __newindex = "not available", __metatable="hidden" } ) ;

--%%%%%%%%%%%%%%%%%%%% Basic Functions %%%%%%%%%%%%%%%%%%%%--{{{1
--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: ADD 
--
--
--  Description:
--     Adds two Big Numbers.
--
--  Parameters:
--     bnum1, bnum2 - Numbers to be added.
--     bnum3 - result
--
--  Returns:
--     0
--
--  Exit assertions:
--     bnum3 is the result of the sum.
--
--  %%%%%%%% --
--Funcao BigNum.add{{{2
function BigNum.add( bnum1 , bnum2 , bnum3 )
	local maxlen = 0 ;
	local i = 0 ;
	local carry = 0 ;
	local signal = '+' ;
	local old_len = 0 ;
	--Handle the signals
	if bnum1 == nil or bnum2 == nil or bnum3 == nil then
		error("Function BigNum.add: parameter nil") ;
	elseif bnum1.signal == '-' and bnum2.signal == '+' then
		bnum1.signal = '+' ;
		BigNum.sub( bnum2 , bnum1 , bnum3 ) ;

		if not rawequal(bnum1, bnum3) then
			bnum1.signal = '-' ;
		end
		return 0 ;
	elseif bnum1.signal == '+' and bnum2.signal == '-' then   
		bnum2.signal = '+' ;
		BigNum.sub( bnum1 , bnum2 , bnum3 ) ;
		if not rawequal(bnum2, bnum3) then
			bnum2.signal = '-' ;
		end
		return 0 ;
	elseif bnum1.signal == '-' and bnum2.signal == '-' then
		signal = '-' ;
	end
	--
	old_len = bnum3.len ;
	if bnum1.len > bnum2.len then
		maxlen = bnum1.len ;
	else
		maxlen = bnum2.len ;
		bnum1 , bnum2 = bnum2 , bnum1 ;
	end
	--School grade sum
	for i = 0 , maxlen - 1 do
		if bnum2[i] ~= nil then
			bnum3[i] = bnum1[i] + bnum2[i] + carry ;
		else
			bnum3[i] = bnum1[i] + carry ;
		end
		if bnum3[i] >= RADIX then
			bnum3[i] = bnum3[i] - RADIX ;
			carry = 1 ;
		else
			carry = 0 ;
		end
	end
	--Update the answer's size
	if carry == 1 then
		bnum3[maxlen] = 1 ;
	end
	bnum3.len = maxlen + carry ;
	bnum3.signal = signal ;
	for i = bnum3.len, old_len do
		bnum3[i] = nil ;
	end
	return 0 ;
end


--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: SUB 
--
--
--  Description:
--     Subtracts two Big Numbers.
--
--  Parameters:
--     bnum1, bnum2 - Numbers to be subtracted.
--     bnum3 - result
--
--  Returns:
--     0
--
--  Exit assertions:
--     bnum3 is the result of the subtraction.
--
--  %%%%%%%% --
--Funcao BigNum.sub{{{2
function BigNum.sub( bnum1 , bnum2 , bnum3 )
	local maxlen = 0 ;
	local i = 0 ;
	local carry = 0 ;
	local old_len = 0 ;
	--Handle the signals

	if bnum1 == nil or bnum2 == nil or bnum3 == nil then
		error("Function BigNum.sub: parameter nil") ;
	elseif bnum1.signal == '-' and bnum2.signal == '+' then
		bnum1.signal = '+' ;
		BigNum.add( bnum1 , bnum2 , bnum3 ) ;
		bnum3.signal = '-' ;
		if not rawequal(bnum1, bnum3) then
			bnum1.signal = '-' ;
		end
		return 0 ;
	elseif bnum1.signal == '-' and bnum2.signal == '-' then
		bnum1.signal = '+' ;
		bnum2.signal = '+' ;
		BigNum.sub( bnum2, bnum1 , bnum3 ) ;
		if not rawequal(bnum1, bnum3) then
			bnum1.signal = '-' ;
		end
		if not rawequal(bnum2, bnum3) then
			bnum2.signal = '-' ;
		end
		return 0 ;
	elseif bnum1.signal == '+' and bnum2.signal == '-' then
		bnum2.signal = '+' ;
		BigNum.add( bnum1 , bnum2 , bnum3 ) ;
		if not rawequal(bnum2, bnum3) then
			bnum2.signal = '-' ;
		end
		return 0 ;
	end
	--Tests if bnum2 > bnum1
	if BigNum.compareAbs( bnum1 , bnum2 ) == 2 then
		BigNum.sub( bnum2 , bnum1 , bnum3 ) ;
		bnum3.signal = '-' ;
		return 0 ;
	else
		maxlen = bnum1.len ;
	end
	old_len = bnum3.len ;
	bnum3.len = 0 ;
	--School grade subtraction
	for i = 0 , maxlen - 1 do
		if bnum2[i] ~= nil then
			bnum3[i] = bnum1[i] - bnum2[i] - carry ;
		else
			bnum3[i] = bnum1[i] - carry ;
		end
		if bnum3[i] < 0 then
			bnum3[i] = RADIX + bnum3[i] ;
			carry = 1 ;
		else
			carry = 0 ;
		end

		if bnum3[i] ~= 0 then
			bnum3.len = i + 1 ;
		end
	end
	bnum3.signal = '+' ;
	--Check if answer's size if zero
	if bnum3.len == 0 then
		bnum3.len = 1 ;
		bnum3[0]  = 0 ;
	end
	if carry == 1 then
		error( "Error in function sub" ) ;
	end
	for i = bnum3.len , max( old_len , maxlen - 1 ) do
		bnum3[i] = nil ;
	end
	return 0 ;
end


--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: MUL 
--
--
--  Description:
--     Multiplies two Big Numbers.
--
--  Parameters:
--     bnum1, bnum2 - Numbers to be multiplied.
--     bnum3 - result
--
--  Returns:
--     0
--
--  Exit assertions:
--     bnum3 is the result of the multiplication.
--
--  %%%%%%%% --
--BigNum.mul{{{2
--can't be made in place
function BigNum.mul( bnum1 , bnum2 , bnum3 )
	local i = 0 ; local j = 0 ;
	local temp = BigNum.new( ) ;
	local temp2 = 0 ;
	local carry = 0 ;
	local oldLen = bnum3.len ;
	if bnum1 == nil or bnum2 == nil or bnum3 == nil then
		error("Function BigNum.mul: parameter nil") ;
		--Handle the signals
	elseif bnum1.signal ~= bnum2.signal then
		BigNum.mul( bnum1 , -bnum2 , bnum3 ) ;
		bnum3.signal = '-' ;
		return 0 ;
	end
	bnum3.len =  ( bnum1.len ) + ( bnum2.len ) ;
	--Fill with zeros
	for i = 1 , bnum3.len do
		bnum3[i - 1] = 0 ;
	end
	--Places nil where passes through this
	for i = bnum3.len , oldLen do
		bnum3[i] = nil ;
	end
	--School grade multiplication
	for i = 0 , bnum1.len - 1 do
		for j = 0 , bnum2.len - 1 do
			carry =  ( bnum1[i] * bnum2[j] + carry ) ;
			carry = carry + bnum3[i + j] ;
			bnum3[i + j] = math.fmod ( carry , RADIX ) ;
			temp2 = bnum3[i + j] ;
			carry =  math.floor ( carry / RADIX ) ;
		end
		if carry ~= 0 then
			bnum3[i + bnum2.len] = carry ;
		end
		carry = 0 ;
	end

	--Update the answer's size
	for i = bnum3.len - 1 , 1 , -1 do
		if bnum3[i] ~= nil and bnum3[i] ~= 0 then
			break ;
		else
			bnum3[i] = nil ;
		end
		bnum3.len = bnum3.len - 1 ;
	end
	return 0 ; 
end


--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: DIV 
--
--
--  Description:
--     Divides bnum1 by bnum2.
--
--  Parameters:
--     bnum1, bnum2 - Numbers to be divided.
--     bnum3 - result
--     bnum4 - remainder
--
--  Returns:
--     0
--
--  Exit assertions:
--     bnum3 is the result of the division.
--     bnum4 is the remainder of the division.
--
--  %%%%%%%% --
--BigNum.div{{{2
function BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 )
	local temp = BigNum.new() ;
	local temp2 = BigNum.new() ;
	local one = BigNum.new( "1" ) ;
	local zero = BigNum.new( "0" ) ;
	--Check division by zero
	if BigNum.compareAbs( bnum2 , zero ) == 0 then
		error( "Function BigNum.div: Division by zero" ) ;
	end     
	--Handle the signals
	if bnum1 == nil or bnum2 == nil or bnum3 == nil or bnum4 == nil then
		error( "Function BigNum.div: parameter nil" ) ;
	elseif bnum1.signal == "+" and bnum2.signal == "-" then
		bnum2.signal = "+" ;
		BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
		bnum2.signal = "-" ;
		bnum3.signal = "-" ;
		return 0 ;
	elseif bnum1.signal == "-" and bnum2.signal == "+" then
		bnum1.signal = "+" ;
		BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
		bnum1.signal = "-" ;
		if bnum4 < zero then --Check if remainder is negative
			BigNum.add( bnum3 , one , bnum3 ) ;
			BigNum.sub( bnum2 , bnum4 , bnum4 ) ;
		end
		bnum3.signal = "-" ;
		return 0 ;
	elseif bnum1.signal == "-" and bnum2.signal == "-" then
		bnum1.signal = "+" ;
		bnum2.signal = "+" ;
		BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
		bnum1.signal = "-" ;
		if bnum4 < zero then --Check if remainder is negative      
			BigNum.add( bnum3 , one , bnum3 ) ;
			BigNum.sub( bnum2 , bnum4 , bnum4 ) ;
		end
		bnum2.signal = "-" ;
		return 0 ;
	end
	temp.len = bnum1.len - bnum2.len - 1 ;

	--Reset variables
	BigNum.change( bnum3 , "0" ) ;
	BigNum.change( bnum4 , "0" ) ; 

	BigNum.copy( bnum1 , bnum4 ) ;

	--Check if can continue dividing
	while( BigNum.compareAbs( bnum4 , bnum2 ) ~= 2 ) do
		if bnum4[bnum4.len - 1] >= bnum2[bnum2.len - 1] then
			BigNum.put( temp , math.floor( bnum4[bnum4.len - 1] / bnum2[bnum2.len - 1] ) , bnum4.len - bnum2.len ) ;
			temp.len = bnum4.len - bnum2.len + 1 ;
		else
			BigNum.put( temp , math.floor( ( bnum4[bnum4.len - 1] * RADIX + bnum4[bnum4.len - 2] ) / bnum2[bnum2.len -1] ) , bnum4.len - bnum2.len - 1 ) ;
			temp.len = bnum4.len - bnum2.len ;
		end

		if bnum4.signal ~= bnum2.signal then
			temp.signal = "-";
		else
			temp.signal = "+";
		end
		BigNum.add( temp , bnum3 , bnum3 )  ;
		temp = temp * bnum2 ;
		BigNum.sub( bnum4 , temp , bnum4 ) ;
	end

	--Update if the remainder is negative
	if bnum4.signal == '-' then
		decr( bnum3 ) ;
		BigNum.add( bnum2 , bnum4 , bnum4 ) ;
	end
	return 0 ;
end

--%%%%%%%%%%%%%%%%%%%% Compound Functions %%%%%%%%%%%%%%%%%%%%--{{{1

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: POW / EXP  
--
--
--  Description:
--     Computes a big number which represents the bnum2-th power of bnum1.
--
--  Parameters:
--     bnum1 - base
--     bnum2 - expoent
--
--  Returns:
--     Returns a big number which represents the bnum2-th power of bnum1.
--
--  %%%%%%%% --
--BigNum.exp{{{2
function BigNum.pow( bnum1 , bnum2 )
	local n = BigNum.new( bnum2 ) ;
	local y = BigNum.new( 1 ) ;
	local z = BigNum.new( bnum1 ) ;
	local zero = BigNum.new( "0" ) ;
	if bnum2 < zero then
		error( "Function BigNum.exp: domain error" ) ;
	elseif bnum2 == zero then
		return y ;
	end
	while 1 do
		if math.fmod( n[0] , 2 ) == 0 then
			n = n / 2 ;
		else
			n = n / 2 ;
			y = z * y  ;
			if n == zero then
				return y ;
			end
		end
		z = z * z ;
	end
end
-- Portugu�s :
BigNum.exp = BigNum.pow

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: GCD / MMC
--
--
--  Description:
--     Computes the greatest commom divisor of bnum1 and bnum2.
--
--  Parameters:
--     bnum1, bnum2 - positive numbers
--
--  Returns:
--     Returns a big number witch represents the gcd between bnum1 and bnum2.
--
--  %%%%%%%% --
--BigNum.gcd{{{2
function BigNum.gcd( bnum1 , bnum2 )
	local a = {} ;
	local b = {} ;
	local c = {} ;
	local d = {} ;
	local zero = {} ;
	zero = BigNum.new( "0" ) ;
	if bnum1 == zero or bnum2 == zero then
		return BigNum.new( "1" ) ;
	end
	a = BigNum.new( bnum1 ) ;
	b = BigNum.new( bnum2 ) ;
	a.signal = '+' ;
	b.signal = '+' ;
	c = BigNum.new() ;
	d = BigNum.new() ;
	while b > zero do
		BigNum.div( a , b , c , d ) ;
		a , b , d = b , d , a ;
	end
	return a ;
end
-- Portugu�s: 
BigNum.mmc = BigNum.gcd

--%%%%%%%%%%%%%%%%%%%% Comparison Functions %%%%%%%%%%%%%%%%%%%%--{{{1

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: EQ
--
--
--  Description:
--     Compares two Big Numbers.
--
--  Parameters:
--     bnum1, bnum2 - numbers
--
--  Returns:
--     Returns true if they are equal or false otherwise.
--
--  %%%%%%%% --
--BigNum.eq{{{2
function BigNum.eq( bnum1 , bnum2 )
	if BigNum.compare( bnum1 , bnum2 ) == 0 then
		return true ;
	else
		return false ;
	end
end

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: LT
--
--
--  Description:
--     Verifies if bnum1 is lesser than bnum2.
--
--  Parameters:
--     bnum1, bnum2 - numbers
--
--  Returns:
--     Returns true if bnum1 is lesser than bnum2 or false otherwise.
--
--  %%%%%%%% --
--BigNum.lt{{{2
function BigNum.lt( bnum1 , bnum2 )
	if BigNum.compare( bnum1 , bnum2 ) == 2 then
		return true ;
	else
		return false ;
	end
end


--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: LE
--
--
--  Description:
--     Verifies if bnum1 is lesser or equal than bnum2.
--
--  Parameters:
--     bnum1, bnum2 - numbers
--
--  Returns:
--     Returns true if bnum1 is lesser or equal than bnum2 or false otherwise.
--
--  %%%%%%%% --
--BigNum.le{{{2
function BigNum.le( bnum1 , bnum2 )
	local temp = -1 ;
	temp = BigNum.compare( bnum1 , bnum2 )
	if temp == 0 or temp == 2 then
		return true ;
	else
		return false ;
	end
end

--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: Compare Absolute Values
--
--
--  Description:
--     Compares absolute values of bnum1 and bnum2.
--
--  Parameters:
--     bnum1, bnum2 - numbers
--
--  Returns:
--     1 - |bnum1| > |bnum2|
--     2 - |bnum1| < |bnum2|
--     0 - |bnum1| = |bnum2|
--
--  %%%%%%%% --
--BigNum.compareAbs{{{2
function BigNum.compareAbs( bnum1 , bnum2 )
	if bnum1 == nil or bnum2 == nil then
		error("Function compare: parameter nil") ;
	elseif bnum1.len > bnum2.len then
		return 1 ;
	elseif bnum1.len < bnum2.len then
		return 2 ;
	else
		local i ;
		for i = bnum1.len - 1 , 0 , -1 do
			if bnum1[i] > bnum2[i] then
				return 1 ;
			elseif bnum1[i] < bnum2[i] then
				return 2 ;
			end
		end
	end
	return 0 ;
end


--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: Compare 
--
--
--  Description:
--     Compares values of bnum1 and bnum2.
--
--  Parameters:
--     bnum1, bnum2 - numbers
--
--  Returns:
--     1 - |bnum1| > |bnum2|
--     2 - |bnum1| < |bnum2|
--     0 - |bnum1| = |bnum2|
--
--  %%%%%%%% --
--BigNum.compare{{{2
function BigNum.compare( bnum1 , bnum2 )
	local signal = 0 ;

	if bnum1 == nil or bnum2 == nil then
		error("Funtion BigNum.compare: parameter nil") ;
	elseif bnum1.signal == '+' and bnum2.signal == '-' then
		return 1 ;
	elseif bnum1.signal == '-' and bnum2.signal == '+' then
		return 2 ;
	elseif bnum1.signal == '-' and bnum2.signal == '-' then
		signal = 1 ;
	end
	if bnum1.len > bnum2.len then
		return 1 + signal ;
	elseif bnum1.len < bnum2.len then
		return 2 - signal ;
	else
		local i ;
		for i = bnum1.len - 1 , 0 , -1 do
			if bnum1[i] > bnum2[i] then
				return 1 + signal ;
			elseif bnum1[i] < bnum2[i] then
				return 2 - signal ;
			end
		end
	end
	return 0 ;
end         


--%%%%%%%%%%%%%%%%%%%% Low level Functions %%%%%%%%%%%%%%%%%%%%--{{{1
--BigNum.copy{{{2
function BigNum.copy( bnum1 , bnum2 )
	if bnum1 ~= nil and bnum2 ~= nil then
		local i ;
		for i = 0 , bnum1.len - 1 do
			bnum2[i] = bnum1[i] ;
		end
		bnum2.len = bnum1.len ;
	else
		error("Function BigNum.copy: parameter nil") ;
	end
end


--%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
--
--  Function: Change
--
--  Description:
--     Changes the value of a BigNum.
--     This function is called by BigNum.new.
--
--  Parameters:
--     bnum1, bnum2 - numbers
--
--  Returns:
--     1 - |bnum1| > |bnum2|
--     2 - |bnum1| < |bnum2|
--     0 - |bnum1| = |bnum2|
--
--  %%%%%%%% --
--BigNum.change{{{2
function BigNum.change( bnum1 , num )
	local j = 0 ;
	local len = 0  ;
	local num = num ;
	local l ;
	local oldLen = 0 ;
	if bnum1 == nil then
		error( "BigNum.change: parameter nil" ) ;
	elseif type( bnum1 ) ~= "table" then
		error( "BigNum.change: parameter error, type unexpected" ) ;
	elseif num == nil then
		bnum1.len = 1 ;
		bnum1[0] = 0 ;
		bnum1.signal = "+";
	elseif type( num ) == "table" and num.len ~= nil then  --check if num is a big number
		--copy given table to the new one
		for i = 0 , num.len do
			bnum1[i] = num[i] ;
		end
		if num.signal ~= '-' and num.signal ~= '+' then
			bnum1.signal = '+' ;
		else
			bnum1.signal = num.signal ;
		end
		oldLen = bnum1.len ;
		bnum1.len = num.len ;
	elseif type( num ) == "string" or type( num ) == "number" then
		if string.sub( num , 1 , 1 ) == '+' or string.sub( num , 1 , 1 ) == '-' then
			bnum1.signal = string.sub( num , 1 , 1 ) ;
			num = string.sub(num, 2) ;
		else
			bnum1.signal = '+' ;
		end
		num = string.gsub( num , " " , "" ) ;
		local sf = string.find( num , "e" ) ;
		--Handles if the number is in exp notation
		if sf ~= nil then
			num = string.gsub( num , "%." , "" ) ;
			local e = string.sub( num , sf + 1 ) ;
			e = tonumber(e) ;
			if e ~= nil and e > 0 then 
				e = tonumber(e) ;
			else
				error( "Function BigNum.change: string is not a valid number" ) ;
			end
			num = string.sub( num , 1 , sf - 2 ) ;
			for i = string.len( num ) , e do
				num = num .. "0" ;
			end
		else
			sf = string.find( num , "%." ) ;
			if sf ~= nil then
				num = string.sub( num , 1 , sf - 1 ) ;
			end
		end

		l = string.len( num ) ;
		oldLen = bnum1.len ;
		if (l > RADIX_LEN) then
			local mod = l-( math.floor( l / RADIX_LEN ) * RADIX_LEN ) ;
			for i = 1 , l-mod, RADIX_LEN do
				bnum1[j] = tonumber( string.sub( num, -( i + RADIX_LEN - 1 ) , -i ) );
				--Check if string dosn't represents a number
				if bnum1[j] == nil then
					warn( "Function BigNum.change: string is not a valid number" ) ;
					bnum1.len = 0 ;
					return 1 ;
				end
				j = j + 1 ; 
				len = len + 1 ;
			end
			if (mod ~= 0) then
				bnum1[j] = tonumber( string.sub( num , 1 , mod ) ) ;
				bnum1.len = len + 1 ;
			else
				bnum1.len = len ;            
			end
			--Eliminate trailing zeros
			for i = bnum1.len - 1 , 1 , -1 do
				if bnum1[i] == 0 then
					bnum1[i] = nil ;
					bnum1.len = bnum1.len - 1 ;
				else
					break ;
				end
			end

		else     
			-- string.len(num) <= RADIX_LEN
			bnum1[j] = tonumber( num ) ;
			bnum1.len = 1 ;
		end
	else
		error( "Function BigNum.change: parameter error, type unexpected" ) ;
	end

	--eliminates the deprecated higher order 'algarisms'
	if oldLen ~= nil then
		for i = bnum1.len , oldLen do
			bnum1[i] = nil ;
		end
	end

	return 0 ;
end 

--BigNum.put{{{2
--Places int in the position pos of bignum, fills before with zeroes and
--after with nil.
function BigNum.put( bnum , int , pos )
	if bnum == nil then
		error("Function BigNum.put: parameter nil") ;
	end
	local i = 0 ;
	for i = 0 , pos - 1 do
		bnum[i] = 0 ;
	end
	bnum[pos] = int ;
	for i = pos + 1 , bnum.len do
		bnum[i] = nil ;
	end
	bnum.len = pos ;
	return 0 ;
end

--printraw{{{2
function printraw( bnum )
	local i = 0 ;
	if bnum == nil then
		error( "Function printraw: parameter nil" ) ;
	end
	while 1 == 1 do
		if bnum[i] == nil then
			print( ' len '..bnum.len ) ;
			if i ~= bnum.len then
				print( ' ERRO!!!!!!!!' ) ;
			end
			print( "\n" ) ;
			return 0 ;
		end
		print( 'r'..bnum[i] ) ;
		i = i + 1 ;
	end
end
--max{{{2
function max( int1 , int2 )
	if int1 > int2 then
		return int1 ;
	else
		return int2 ;
	end
end

--decr{{{2
function decr( bnum1 )
	local temp = {} ;
	temp = BigNum.new( "1" ) ;
	BigNum.sub( bnum1 , temp , bnum1 ) ;
	return 0 ;
end

return BigNum
1 Like

That’s the maximum value 64-bit numbers are able to get(9,223,372,036,854,775,807) . You may want to find a workaround like only keeping the first digits(for example first 5) and their type(example 5.432k). Although if you chose this you may have to make custom functions to increase/decrease the values and to visualize them.

PS: an easier solution is what @Inconcludable suggested.

Thank you both for your replies, but while further researching topics on using BigNum I stumbled upon a reply saying that only IntValues have that cap, and if I switched to instead use NumberValues then I would no longer have such issue, so I have just tested it and sure enough it worked!

P.S that guy said NumberValue cap is 10^300

1 Like

NumberValues still have a cap, it’s just much higher. It caps off at about 5e+307, and loses an insane amount of precision along the way. Once it reaches the cap, it turns into inf. However, if you’re fine with loss of precision and the cap (and the possible bugs once it rolls over to inf), I suppose that works.

I don’t think that players will make it to 5e+307 anytime soon, but once we get that far I might have to use BigNum anyways. I was just wondering how I can access the BigNum from multiple scripts?

You’d want to put it in a ModuleScript, then require it from a normal script. Example usage:

local BigNum = require(game:GetService("ServerScriptService").BigNum)

print((require(game.ServerScriptService.BigNum).new("2")^500)) 
-- This outputs 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376

The nice thing about this module is that you can almost always use it like a normal number.

Yes I know I have done that already my problem is getting that created BigNum created in a reg script, into other scripts

You could try using a StringValue.
This method doesn’t seem terribly efficient, but you could use the .Changed event from the StringValue to easily detect changes. Here’s how it works:

local BigNum = require(game:GetService("ServerScriptService").BigNum)

local Number =  BigNum.new("2")^500
workspace.StringValue.Value = tostring(Number) 


-- In another script
local BigNum = require(game:GetService("ServerScriptService").BigNum)

local Value = workspace.StringValue
local Number = 0

Value.Changed:Connect(function(Value)
	Number = BigNum.new(Value)
end

I would use BindableEvents, but BindableEvents don’t preserve metatables.

I’ll give it a shot. I’m not sure if I remember correctly now but I think it was either for floats or strings (I’m pretty sure it was floats) but before I thought it was strings, that have a 13 max length cap, but now I thought about it harder and I thing it was a float with a cap of 13 decimals. So none of that matters now but thanks for your help!