InfiniteMath | Go above 10^308/1e+308!

Can I trust the module for accuracy? (not precision but accuracy!). I don’t want a module that can represent up to 10^(10^308) with semantics that is not very accurate and not good.
Can I trust the module to have semantics I can predict (and anything with contrary semantic should be documented)?

Why just extend the exponent?
Are you aware you are mixing binary floating point with base-10 exponents? Why not base-2 exponents?

Did you take account of negative exponents? If not, why just positive, and is the exponent offseted by a constant (called ‘biased exponent’)?

What abstract numerical data type is this trying to represent? If it’s an abstract scalar floating point - what’s the exact precision (in bits, digits, etc) of the significand and the exact width of exponent?

Looking at the module and the source code, it doesn’t suggest that you understand floating point semantics very well. You aren’t aware that sqrt(x) and x^0.5 are different for -0.0 and -Infinity. In fact, you don’t seem to have a sufficient understanding of the concept of floor and ceil, the documentation is quite ambiguous “Rounds a number down to the nearest integer” (what does it do for negative floats?), and function named floor actually rounds towards zero (should’ve made that more clear in the documentation if that is intentional) which is in contrast to what I expect floor does given that the semantics of the floor is usually defined as rounding towards negative infinity in lots of programming language standard and in math (Floor Function – from Wolfram MathWorld). Additionally, these functions doesn’t even work for exponents >= 3 because of this if second >= 3 then return Num * sign end in the floor implementation, what’s your reason to have a guard clause of this (I don’t think it is an edge case as it checks if exponent is >= 3 which is common), and the variable name second is an odd choice)? …and this isn’t documented so I’m unsure if this is a bug or an intentional behaviour.
Also, using tostring to check for NaN (which I saw in the __eq method of InfiniteNum) isn’t a good idea nor it will be assured to work as you expect as tostring could return -nan, -nan(ind), nan(snan) etc as tostring is platform and implementation dependent, along the fact that converting a number to strings is quite an expensive process.
That’s my concern with this module.

I think metamethods are used for ergonomics purposes. Why would this be a real problem for a multi-precision library? Sure, it’s not as ergonomic.

Why would this be a deal breaker?

These instructions call functions under the hood if raw operations of these (such as number + number) aren’t available so I don’t think this brings any advantages other than ergonomics.

2 Likes

A lot of what you’ve mentioned is simply just because of me lacking math skills. I made this module a few years ago with someone smarter than me to help with the math. A few months ago I told some friends about the module and my problems with it, and they decided to help improve the module.

I thought it would be a good idea to open source it, not only so people could use it, but so it could be improved as well.

Most of the accuracy issues are from me missing them, like floor rounding towards zero instead of negative infinity, I just didn’t think/didn’t know about it.

This was because I couldn’t figure out round/ceil/floor while keeping the coefficient and exponent separated (at least with usable performance), so I used the normal functions and assumed rounding after 1000 wouldn’t matter because it would be displayed with one of the notation functions (compact/scientific notation)

Before I learned the correct terms, I used first and second (first for coefficient, second for exponent), and it just never got changed.

Instead of having negative exponents, the coefficient is allowed to go between 0 and 1 for decimals when the exponent is 0. It made implementing arithmetic easier for me.

The metamethods are just there to make using this module look and feel easier. All the .add and .multiply functions will add up and it starts to get confusing, its a lot easier to just be able to use + or -. There is no real gain for this besides ease of use, and I think its important.

The module is built for games like simulators/tycoons, which normally will have a global leaderboard for players. Its important for some games, so they might prefer this module just for having that support.

This module definitely isn’t accurate in the way you describe, like you already mentioned there are multiple inaccuracies. I believe for a simulator/tycoon game, it would be accurate enough, unless there is a heavy focus on math and it being correct.

The reason I open sourced it is in the hope that people smarter than me would point these things out and maybe even fix them, and so that people who maybe don’t care about 100% accuracy could have a module with easier use (I believe) than the current alternatives.

2 Likes

He just doesn’t understand the purpose of it, because he probably doesn’t play simulators or tycoons. He had similar arguments toward my post, and while I do understand his concerns, I don’t think he quite understands why we make/use these kinds of modules on Roblox.

2 Likes

I think he has a few points on accuracy, but yeah it does seem like he doesn’t really understand the purpose of the module being for tycoons and simulators.

2 Likes

1.3.2 is here, another small update that fixes a few things.

  • Fixed floor and ceil accuracy with negative numbers.
  • Improved the __eq nan check by removing tostring usage. nan is already stored as a string, so using tostring is pointless.
  • Fixed errors when creating a Number with -0. The created number will have a value of 0. If you need the value to be -0, please give a usage case.

Get just the module here: InfiniteMath - Roblox

2 Likes

Heya, following up on this - could you publish this to Wally, as that would be useful for many people wanting to use libraries as such.

2 Likes

We actually already have Wally setup!

1 Like

My bad, just realized it a bit back.

I’d also like to append a feature request here: would be cool to have bitwise operator support for InfiniteMath, I can see this especially useful in cryptography.

1 Like

1.3.3 is here, very small update to fix an error.

  • Fixed an error with round between 1e+100 and 1e+299
1 Like

Ok should have look around a little more haha, 1.3.4 here with another tiny fix

  • Improves Reverse by removing string usage, and instead solving the scientific notation equation ({5, 7} = 5 * 10^7 = 50000000). This fixes an error with very small decimals that use e-.
2 Likes

1.3.5 is here, with performance improvements thanks to Native Code Gen

  • Marks the module as native (with --!native) to increase performance.

Using this function before this update will take approx 2.6201 seconds. After this update it takes approx 1.6117 seconds (38.48% improvement). Certain functions are impacted more than others (only using new results in an 8.45% improvement)

local IM = require(game.ReplicatedStorage.InfiniteMath)

local ticker = tick()

for i = 1, 100000 do
	local Num = IM.new(i)
	
	Num *= i
	
	Num ^= i
	
	Num = IM.round(Num)
end

print(tick() - ticker)

Currently, you need to enable the Luau Native Code beta to see the effects, and live servers will not be impacted.

3 Likes

1.3.6 is here. This update fixes a few bugs.

  • Fixed an issue with InfiniteMath.new() where strings such as "1e+5" or "50000" would error.

  • Fixed an issue where if DECIMALPOINT cuts off the decimal of a number display such as 10.00025, it would display with zeros after the point, like 10.00. If the decimal of a displaying number (using GetSuffix) is equal to 0, it will be removed. 10.00 turns into 10.

  • Fixed an issue where super low decimals that get turned into Scientific Notation, such as 5e-5 which equals 0.00005 would cause multiple errors.

1 Like

I’m sorry but you seem to have made a misleading and very minor mistake. 10^10^308 is vastly different from 10^^308. 10^^308 is actually 10^10^10^…^10 308 times in total.

10^^308 in full length:

10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10^10
(a tad bit larger than 10^10^308)

1 Like

The limit actually is 10^^308 (10^10^10…^10 308 times.)

local IM = require(game.ReplicatedStorage.InfiniteMath)

local Num = IM.new(10)

for i = 1, 308 do
	Num = Num^10
end

print(Num.first, Num.second, Num)

This code prints the coefficient, the exponent, and the scientific notation of the number.

1 9.999999999999998e+307 1e+99.99UC is the print, coefficient is 1 and exponent is basically 1e+308.

I don’t believe I say the limit is 10^10^308 anywhere, unless I missed it when I was replacing it with 10^^308. Can you let me know where it says 10^10^308?

2 Likes

My bad. I guess I was thrown off at the start by

It doesn’t directly state 10^10^308 but I pretty quickly assumed that’s what you were referring to.

1 Like

Ah its okay, at one point the post said it was 10^10^308 before I learned its actually 10^^308, so I thought it might still say that somewhere.

1 Like

1.3.7 is here with some bug fixes!

  • Fixes the .00 fix not working with DECIMALPOINT not being 2, .000 or .0 will now be fixed just like .00.

  • Fixed .99 showing up at the end of numbers that are very close to being whole. For example 5 might be stored as 4.99999999999523525, displaying as 4.99 (decimal amount depending on DECIMALPOINT), numbers ending in a decimal very close to 1 will now be rounded up. 4.99999999999523525 will display as 5.

  • Fixed numbers below 1 not using DECIMALPOINT in :GetSuffix().

  • Fix C stack overflow error when using .__concat with an InfiniteMath number as the second parameter

  • Improved pow is not a valid power error for .__pow, the error now explains that if your power is inf you need to keep it below 10^308.

2 Likes

1.3.8 has been released with some more fixes/improvements, and a new doc on using datastores with InfiniteMath.

  • Fixed a bug with very small numbers (that get stored as scientific notation, like 1e-15) displaying incorrectly.

  • Improves InfiniteMath.round(), reduces cases of incorrectly picking ceil or floor over the other.

  • Added a new Datastore Implementation page to the docs website.

  • Corrects a mistake in the Suffixes module, QNV (Quinvigintillion) was instead QNT, even though there is already QNT (Quattuornonagintaducentillion).

  • Improves some type checking that was added 1.3.7, .new() no longer throws a warning with tables or InfiniteMath numbers.

1 Like

Thank you! Finally I can do my astro physics homework in Roblox

2 Likes

Tbh I like the concept of it but I still prefer EternityNum (Old) by @FoundForces because it’s useful for games and I don’t need to code in suffixes because it’s already preset to 1e(1.78*10^308) and plus it’s easy to learn.

3 Likes