this my good sir is what i would call a banger
good stuff!!! super proud
this my good sir is what i would call a banger
good stuff!!! super proud
Man that is pretty cool. I do not even think that the calculus functions are useless. In fact I was able to approximate pi up to 7 decimal digits correct with just three lines of code :
local Math = require(game.ReplicatedStorage.MathAddons)
s = 2 * Math.integral(-1,1, function(x) return math.sqrt(1-x^2) end)
print(s)
For anyone interested in math here is why this works:
Assume we have a circle with radius 1. Its area is then the following: pi * r^2 = pi * 1 = pi
So, by knowing the area of such a circle we can theoretically calculate pi. We also know that there is a function that describes the curve of the half of the circle which in our case is the following:
Let f(x) be a continuous positive function between a and b and consider the region below the curve y = f(x), above the x-axis and between the vertical lines x = a and x = b. Then denote the area of this region by
and call this the definite integral of f(x) from a to b.
We know our function which is y=f(x)=sqrt(1-x^2) and our points a and b are -1 and 1 respectively. Thus the area under the curve is :
The problem with this though is that the indefinite integral of sqrt(1-x^2) is the following:
Now, you will ask what is the problem with the above? The answer is that the arcsin formula is the following:
arcsin(x) = π/2 - arccos(x) So as you understand we can not find pi using pi because we will end in something like this 0=0. Now, you might ask, how did the above module calculate pi ? The answer is that it did not calculate it, but it approximated it with the following method:
s = sqrt(1-(-1))^2 * 1e-5 + sqrt(1-1^2)*1e-5 + sqrt(1-(1e-5)^2)*1e-5 which then becomes
s = 0 + 0 + sqrt(1-(1e-5)^2) * 1e-5 which when multiplied by two is an approximation of our area and hence of pi.
I have to admit that the methods that are used in both calculus functions are smart because in reality these seemingly random numbers (1e-12) and (1e-5) are small changes(which is exactly what calculus examines, changes) that will approximate the result.
Great work, mate! Would you consider adding a function to convert a string to an equation and an equation to a string?
Input: “3 + 3” OR 3 + 3
Output: 3 + 3 OR “3 + 3”
I was actually planning to make this with the previous version before my previous account was terminated, definitely will work on this next!
I remember I tried to make a pi generator with lebreniz formula. And it was innacurate as hell. Thank you for this.
By the way, in the integral function, you can lower the number “1e-5” so something like 1e-8, the function will take longer to run since its a loop, however this will get you better estimates of pi, or whatever you’re attempting to calculate
Hi, it’s me again. I tried doing some optimizations on your Solver function, and I managed to shave off a considerable amount of processing time.
local module = {}
type math = (number) -> (number)
local flr = math.floor
local ts = tostring
local strL = string.lower
local inf = math.huge
function round(n: number, decimal: number?): number
local factor: number = decimal or 1
return flr(n * factor + .5) / factor
end
function module.Solve(f: math, iterations: number?): {number} --2nd parameter allows for user-set amount of iterations
local iterations = iterations or 1e3 --default iteration amount of 1000
local t: {number} = {}
for i = -20, 20, .1 do
table.insert(t, i)
end
for ii = 1, iterations do
for i, a in ipairs(t) do
local fa: number = f(a)
local num: number = a - 1e-5*fa / (f(a + 1e-5) - fa)
local num2: number = round(num, 1e14)
t[i] = if strL(ts(num2)) == 'nan' then inf else if ii == iterations then num2 else num
end
end
local bl: {true} = {}
local n: {number} = {}
for _, v in ipairs(t) do
local num: number = round(v, 1e10)
if not bl[num] then
bl[num] = true
table.insert(n, num)
end
end
table.sort(n)
return n
end
return module
As for actual output, it’s basically the same. The loss of precision should be negligible for any practical applications.
Edit 2: made some more changes to the script for even more performance
I definitely overlooked performance when making the function, this will be apart of the next version of the module. Thanks for the help once again!
Update 2 - Miniscule Updates & a new module
Thursday, June 30th, 2022
Purpose: find the value of x for an equation in the form of x*e^x when its equal to some number y
Parameters:
Output: Table
Explanation:
Example:
local x = module.lambert(5*math.exp(5)) -- x = 5
local y = module.lambert(3*math.exp(3)) -- y = 3
local z = module.lambert(2) -- z = 0.8526055020137
Purpose: convert a number (complex or not) to an array in the form of {a,b} from the form “a+bi”
Parameters:
Output: Table
Explanation:
Example:
local x = complex.toArray("1+i") -- x = {1,1}
local y = complex.toArray("5-2i") -- y = {5,-2}
local z = complex.toArray("i") -- z = {0,1}
Purpose: convert an array to an string/number in the form of “a+bi” from the form {a,b}
Parameters:
Output: String/Number
Explanation:
Example:
local x = complex.toString({1,1}) -- x = "1+i"
local y = complex.toString({5,-2}) -- y = "5-2i"
local z = complex.toString({0,1}) -- z = "i"
Ive created a new module for graphing functions called Graphit which allows you to graph any function you’d like.
Update 3 - More Complex Number Support
Saturday, July 2nd, 2022
Purpose: calculate x^x, a certain amount of times
Parameters:
Example:
local x = module.tetration(math.sqrt(2),10000) -- x = 2 -- fun fact the infinite tetration of root 2 is 2!!
local y = module.tetration(3) -- y = 3^3=27
local z = module.tetration(i,10000) -- z = 0.43828293672702395+0.3605924718713796i
Purpose: convert a complex number into its real part
Parameters:
Output: String/Number
Explanation:
Example:
local x = complex.Re(1+i) -- x = 1
local y = complex.Re(5-2*i) -- y = 5
local z = complex.Re(i) -- z = 0
Purpose: convert a complex number into its imaginary part
Parameters:
Output: String/Number
Explanation:
Example:
local x = complex.Im(1+i) -- x = 1
local y = complex.Im(5-2*i) -- y = -2
local z = complex.Im(i) -- z = 1
Ive updated the module so that common math functions are compatible with inputs and outputs of complex numbers
And also makes some normal functions compatible with complex numbers
local i = module.Complex.i
print(i^2) -- -1
We are all gathered here to witness the removal of several complex number functions
I dont know what the next update should have, let me know if you have an idea!
It would be helpful if you mentioned some functions (especially the one in the statistics and probability section) mutates the table pointer especially if I expect it to not mutate (MathFunctions.min
, MathFunctions.max
).
print(MathAddons.min({0, -0}))
print(MathAddons.min({-0, 0}))
prints 0
and -0
rather than -0
and -0
. Was this intentional?
MathAddons.mode
actually returns a string
print(type(MathAddons.mode({ 1 })[1]))
even though the documentation stated that the function returns tables of numbers (IEEE).
I don’t think formatting belongs in math. I don’t recommend parsing formatted string (inverse format strings) as formatting is supposed to display numbers and parsing numbers that’s only supposed to show in the UI feels weird to me. What’s your motivation of the parsing functions - fromComma
, fromKMBT
, fromNumeral
, etc?
The semantics is also an issue.
toKMBT
return a number
for values below ±1000 yet in the docs it’s stated that it returns a string
?
print(MathAddons.toKMBT(1) == 1)
prints true
. This is a serious bug in my opinion, as using string methods could error saying attempting to index number value.
toComma
disregards signed zeroes.
ToFraction
also prints 2^-1022
incorrectly as 1/20001 false
, and did not simplify the denominator of 2^53
when finite IEEE 754 binary64 values is a subset rational with the denominator of 2^k.
print(Math.ToFraction(2 ^ -1022))
print(Math.ToFraction(2 ^ 53))
the first is not even a close approximation, and in the second, the denominator could be simplified to 9007199254740992/1
.
Can I ask what’s the point of MathAddons.pi
when math.pi
already exists? Adding more digits doesn’t make it any more precise:
MathFunctions.pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555
as math.pi
is 0x1.921fb54442d18p1
which is represented in IEEE 754 binary64 as 0 10000000000 1001001000011111101101010100010001000010110100011000
and at a VM-level the number
data type in Luau is IEEE 754 binary64 in Roblox.
I noticed that you used pairs
on tables with only ordinal indices, do note that as pairs
has the same behaviour as next
, the order of pairs
and next
is explicitly undefined. You should use ipairs
or generalized iteration instead.
I think semantics of many (or majority) of these is something you should improve in your library.
Thanks for the feedback,
Not necessarily intentional but not a bug either, normal math functions like math.min
and math.max
behave the same way,
print(math.min(0,-0)) -- = 0
print(math.min(-0,0)) -- = -0
print(math.max(0,-0)) -- = 0
print(math.max(-0,0)) -- = -0
this is just how table.sort functions, having -0
deemed greater than 0
is not an actual problem, since when being compared to non 0 numbers, they will function normally since -0
is equal to 0
, and order wont matter.
This was my mistake! I forget that although you can still do and inequalities on numbers in forms of strings, that they wouldn’t remain strings. This will be patched in the next update.
These functions are more applicable compared to other functions, although they perform no actual manipulation or computation of the input, there still is math behind it.
This also will be fixed in the next update.
The module runs a loop which plays a game of hot or cold to guess the fraction, it runs a loop of 20,000 times to get the best approximation possible. for numbers less than 1/20001
I have fixed this however, now the function will scale the input so it becomes larger than 1/20001
, this is what the new values now are
print(Math.ToFraction(2 ^ -1022)) -- = 174619484/7.84780619e315
print(Math.ToFraction(2 ^ 53)) -- = 9007199254740992/1
I’m not sure why you would need the first one in any case since any number with over 308 digits is just considered math.huge,
print(1/math.huge) -- = 0
You make a point, this will be removed in the coming update
This doesn’t make any real difference in the code, however this does seem safer to use in case something does get sorted incorrectly.
I appreciate the criticism, most of your suggestions will be implemented in the next update.
Update 4 - Minor Changes
Saturday, July 9th, 2022
-1000 < x < 1000
1/20001
f(x) = g(x), solve for x
math.pi
Small personal update regarding the module, yesterday my pc overheated (from Roblox haha) and is refusing to turn on. I may have to buy a new one if the circumstances don’t change, which may take a while considering my budget and specifications I need.
To sum it up the next update for the module is probably in september.
(typing from my phone so disregard the organization)
This is an amazing module, still wondering. Has it been updated and/or are you still maintaining it?
sorry for bump
thanks, and it isnt dead! there will be a few more functions coming out like prime factorization, logical operations like xor, nCr, and others things which are only good for mathematical use.
Im still here taking suggestions just i dont have the same time as i did in the summer when i was out of school
Update 5 - Complex Number Support & Optimizations
Sunday, January 8th, 2023
Purpose: Returns x!
Parameters:
Output: Number
Explanation:
Example:
local x = module.factorial(5) -- 120
local y = module.factorial(.5) -- 0.8862269254527584
local z = module.factorial(module.Complex.i) -- 0.49801566812031056-0.15494982830241888i
local a = module.factorial(-2.3) -- 3.3283470067886083
-- module.gamma(x) = module.factorial(x-1)
Purpose: returns the amount of ways to select a group of items where the order of the items does not matter.
Parameters:
Amount of items
Amount of items being selected
Output: Number
Explanation:
Example:
local x = module.nCr(5,3) -- 10
local y = module.nCr(12,4) -- 495
Purpose: returns the amount of ways to select a group of items where the order of the items does matter.
Parameters:
Amount of items
Amount of items being selected
Output: Number
Explanation:
Example:
local x = module.nPr(5,3) -- 60
local y = module.nPr(12,4) -- 11880
Purpose: Returns a given row of the pascals triangle
Parameters:
Output: Number
Explanation:
Example:
local x = module.pascalstri(5) -- {1, 5, 10, 10, 5, 1}
local y = module.pascalstri(3) -- {1, 3, 3, 1}
Purpose: Get the prime factorization of a given input
Parameters:
Output: String
Explanation:
Example:
local x = module.primeFactor(144) -- x = {{3,2},{2,4}} (this is saying 3^2×2^4 = 144
local y = module.toPercent(97) -- y = {{97,1}}
local z = module.toPercent(13*11) -- z = {{13,1},{11,1}}
Purpose: find the value of x for an equation in the form of x*e^x when its equal to some number
Parameters:
Output: Table
Explanation:
Lambert W function - Wikipedia
Example:
local x = module.lambert_w0(5*math.exp(5)) -- x = 5
local y = module.lambert_w0(3*math.exp(3)) -- y = 3
local z = module.lambert_w0(2) -- z = 0.8526055020137
local a = module.lambert_w0(module.Complex.i) -- a = 0.37469902073711625+0.5764127230314329i
local b = module.lambert_w0(-.25) -- b = -0.3574029561813889
Purpose: find the value of x for an equation in the form of x*e^x when its equal to some number
Parameters:
Output: Table
Range: -1/e to 0
Explanation:
Lambert W function - Wikipedia
Example:
local x = module.lambert_wm1(5*math.exp(5)) -- x =
local y = module.lambert_wm1(3*math.exp(3)) -- y =
local z = module.lambert_wm1(2) -- z =
local a = module.lambert_wm1(module.Complex.i) -- a =
local b = module.lambert_wm1(-.25) -- b = -2.15329236411035
More normal functions now can accept inputs and outputs of complex numbers
local i = module.Complex.i
print(i^2) -- -1
Goodbye tau, nobody misses you
Module will recieve minor updates without announcements.
Please suggest functions you would like added!!
ps: thanks to this GitHub - protobi/lambertw: Javascript implementation of Lambert W function had to rewrite the code in lua, and then implement complex support, but i wouldnt have been able without this post
You should really specify the cost of some of these functions. Using a Riemann Sum for the integral function is going to be extremely costly.
This is a useful library.
Have you considered publishing it on GitHub and allowing contributions like the previous version of it?
I have, although I’m not all that familiar with github so I’m not sure if I’ve made a repo to the best of my abilities
I’ve thrown one together here if you’d like one anyway