Change a Decimal to Fraction in JS
decToFrac(3.14159265359) // pi in fraction
// get [355, 113] or simply 355 / 113
Have you ever wondered how to turn chicken soup back into a living chicken? Of course you can’t and it’s not possible. And in mathematics there are also more or less the same problems. If you have a fraction — no matter how big or small — that if you calculate it will produce a decimal. The fraction could be rational (perfectly divisible), or it can be irrational (not perfectly divisible). Regardless of whether the fraction is rational or irrational, the challenge for us is when we receive a decimal number, can we turn it back into a fraction?
Of course there are many sophisticated algorithms outside of this article, from books, journal research, to supercomputer laboratories. But we only have a computer or laptop, and we want to convert a decimal number into a fractions that best represents the decimal number. Why do I use the word “represent”? Because when we receive a decimal number that is so unique — among many alternative fractions we can look for — it is not certain that there is one that may perfectly match given decimal number.
I’m a total beginner in math, only packed with curiosity and a little bit of knowledge in JavaScript language, I would love to create a function that can convert a decimal number back into a fraction. Here is the JS code I made:
decToFrac = dec =>
[...Array(1000).keys()].flatMap(
i => [...Array(1000).keys()].map(
j => [
i + 1, j + 1, (i + 1) / (j + 1),
Math.abs(((i + 1) / (j + 1)) - dec)
]
)
).sort((a, b) => a[3] - b[3])[0].slice(0, 2)
decToFrac
is a function that accepts a decimal number. The first step taken by this function is to create a matrix in size of 1000 * 1000 or 1 million where each row is a series of numbers from 1 to 1000, as well as each column filled with numbers from 1 to 1000. The second step, we transforms each cell in the matrix into an array containing :
- row index
- column index
- decimal result of (row index / column index)
- absolute difference between decimal result and target
The third step is to flatten the matrix into an array of 1 million elements and sort it based on the smallest to the largest absolute difference value. The fourth step is to take the first row and return the first and second elements which are the quantifier and denominator of a fraction.
Of course the function above is not the most efficient algorithm to work with, but at least we can try 1 million possibilities to find which of them is closest to the decimal value we are targeting.
decToFrac( 23.689817948712386928365235 )
// get [687, 29] in 2 seconds
687 / 29 // get 23.689655172413794
// accurate to 3 decimals
In the example of the first line, we try to change a decimal with a length of 24 digits behind the decimal (please have a look). Coupled with the integer in the front, it means that we have a 26-digit number whose closest match we want to find in the matrix created by decToFrac
function. Within about 2 seconds, the console returns a pair of numbers, namely 687 and 29. This means that according to this JS function, the fraction whose decimal value is closest to our target is that pair of numbers.
In the second line is an example of how if we count 687 / 29
, the console will show the result 23.689655172413794
with 15 decimal digits. If we compare it with the decimal number that we gave to the function earlier it is clear that both decimals are not exactly the same. But at least this function is able to calculate with accuracy up to 3 decimal places. If your needs range from economics field to construction engineering, maybe this 3-digit accuracy is enough to satisfy your job needs. But don’t expect this function to be the sole solution for your research in pure mathematics or physics, because they surely will demand much higher accuracy.
// 16 digits / 16 digits
decToFrac( 7528365409872894 / 9876598265498238 )
// get [747, 980] still in 2 seconds
In this last example I tried to feed decToFrac
function with a fraction of 16 digit numbers divided by numbers by equal length. The console outputs [747, 980]
which means that the fraction closest to the decimal result above is 747 / 980
. The interesting thing here is that the first 3 digits of the initial data pair are not even exactly the same as the 3 digit pair generated by the console. This is reasonable since we made our matrix only 1000 * 1000 wide.
So what if we want this function to produce more accurate numbers? Of course you can, simply by modifying the function decToFrac
above by extending the generated matrix. In example:
decToFrac = dec =>
[...Array(10000).keys()].flatMap( // from 1,000 to 10,000
i => [...Array(1000).keys()].map(
j => [
i + 1, j + 1, (i + 1) / (j + 1),
Math.abs(((i + 1) / (j + 1)) - dec)
]
)
).sort((a, b) => a[3] - b[3])[0].slice(0, 2)
With the modified function — to 10000 * 1000- we can produce fractions that are relatively more accurate because the quantifier and denominator pairs that come out can each have 4 and 3 digits. A function that initially only took 2 seconds to solve after clicking “Enter”, now it takes almost half a minute. I’ve also tried modifying it to be a matrix of 10000 * 10000 = one hundred million cells, at first I thought that this function would finish calculating after I made a cup of coffee, but apparently the computer froze and had to restart it again. So if you want to modify the function, go ahead, depending on the needs and computer resources you have.
Thank you, and may it be useful to you.