Square root by approximation - javascript

I am trying to solve this challenge but I don't know if my code is wrong, or if the phrasing of the challenge is wrong. The algorithm says:
Choose two numbers S,E. The X square root must be in [S,E] interval.
Choose the precision desired e.
The middle value of the current interval, M, will be a good approximation.
While the interval [S,E] is greater than e, do:
find the middle value of the current interval M;
if M^2 > x, E = M, otherwise, S = M;
When the length of
our interval is smaller than e, square root of X = M.
My code below produces an infinite loop:
e = 0.001; //I want square root of 10
n = "10";
x = parseInt(n);
E = (x / 2);
S = 1;
M = ((E - S) / 2);
tam = (E - S);
while (tam >= e) {
console.log(M)
if ((M * M) > x) {
E = M;
} else {
S = M
};
M = ((E - S) / 2);
tam = (E - S);
}
console.log(n + ": " + M);
Thanks

You're not finding the midpoint of the interval correctly. You should be adding E and S and dividing by two instead of subtracting.
e=0.001; //I want square root of 10
n="10";
x=parseInt(n);
E=(x/2);
S=1;
M=((E+S)/2);
tam = (E-S);
while(tam>=e){
console.log(M)
if ((M*M)>x){E=M;}else{S=M};
M=((E+S)/2);
tam = (E-S);
} console.log(n+": "+M);

Related

Calculating the Modular Inverse in JavaScript

I am trying to take ed = 1 mod((p-1)(q-1)) and solve for d, just like the RSA algorithm.
e = 5, (p-1)*(q-1) = 249996
I've tried a lot of code in javascript such as:
function modInverse(){
var e = 5;
var p = 499;
var q = 503;
var d = e.modInverse((p-1) * (q-1));
DisplayResult(d, "privateKeyResultLabel")
}
or
function modInverse(){
System.out.println(BigInteger.valueOf(5).modInverse(BigInteger.valueOf(249996)));
}
I just can't figure out the correct way to solve for d, the modular inverse, in javascript.
I was just going through the definition of modular multiplicative inverse and from what I understand:
ax = 1 (mod m)
=> m is a divisor of ax -1 and x is the inverse we are looking for
=> ax - 1 = q*m (where q is some integer)
And the most important thing is gcd(a, m) = 1
i.e. a and m are co-primes
In your case:
ed = 1 mod((p-1)(q-1)) //p, q and e are given
=> ed - 1 = z*((p-1)(q-1)) //where z is some integer and we need to find d
Again from the wikipedia entry, one can compute the modular inverse using the extended Euclidean GCD Algorithm which does the following:
ax + by = g //where g = gcd(a,b) i.e. a and b are co-primes
//The extended gcd algorithm gives us the value of x and y as well.
In your case the equation would be something like this:
ed - z*((p-1)(q-1)) = 1; //Compare it with the structure given above
a -> e
x -> d
b -> (p-1)(q-1)
y -> z
So if we just apply that algorithm to this case, we will get the values of d and z.
For ax + by = gcd(a,b), the extended gcd algorithm could look something like (source):
function xgcd(a, b) {
if (b == 0) {
return [1, 0, a];
}
temp = xgcd(b, a % b);
x = temp[0];
y = temp[1];
d = temp[2];
return [y, x-y*Math.floor(a/b), d];
}
This algorithm runs in time O(log(m)^2), assuming |a| < m, and is generally more efficient than exponentiation.
I don't know if there is an inbuilt function for this in javascript. I doubt if there is, and I am a fan of algorithms, so I thought you might want to give this approach a try. You can fiddle with it and change it to handle your range of values and I hope it gets you started in the right direction.
This implementation of modular inverse can accept any type of inputs. If input types are not supported, NaN is returned. Also, it does not use recursion.
function modInverse(a, m) {
// validate inputs
[a, m] = [Number(a), Number(m)]
if (Number.isNaN(a) || Number.isNaN(m)) {
return NaN // invalid input
}
a = (a % m + m) % m
if (!a || m < 2) {
return NaN // invalid input
}
// find the gcd
const s = []
let b = m
while(b) {
[a, b] = [b, a % b]
s.push({a, b})
}
if (a !== 1) {
return NaN // inverse does not exists
}
// find the inverse
let x = 1
let y = 0
for(let i = s.length - 2; i >= 0; --i) {
[x, y] = [y, x - y * Math.floor(s[i].a / s[i].b)]
}
return (y % m + m) % m
}
// Tests
console.log(modInverse(1, 2)) // = 1
console.log(modInverse(3, 6)) // = NaN
console.log(modInverse(25, 87)) // = 7
console.log(modInverse(7, 87)) // = 25
console.log(modInverse(19, 1212393831)) // = 701912218
console.log(modInverse(31, 73714876143)) // = 45180085378
console.log(modInverse(3, 73714876143)) // = NaN
console.log(modInverse(-7, 87)) // = 62
console.log(modInverse(-25, 87)) // = 80
console.log(modInverse(0, 3)) // = NaN
console.log(modInverse(0, 0)) // = NaN

elgamal decryption in javascript

i need a way to calculate:
m = a. b ^(p-1-x) mod p
in javascript.
i have found this algorithm for calculating base^exp%mod:
function expmod(base, exp, mod){
if (exp == 0) return 1;
if (exp % 2 == 0){
return Math.pow((this.expmod(base, (exp / 2), mod)), 2) % mod;
}
else {
return (base * (this.expmod(base, (exp - 1), mod))) % mod;
}
}
and it's works great. but I can't seem to find a way to do this for
m = a. b ^(p-1-x) mod p
i'm sorry if this question not perfect. this is my first question here. thank you.
I have no experience with cryptography, but, since no one else is answering, I'll give it a shot.
Your question didn't quite make sense to me the way it was phrased, so I decided to implement a complete Elgamal in JavaScript so that I could understand your problem in context. Here's what I came up with:
// Abstract:
var Alphabet = "!\"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ \n𮃩∆";
Alphabet = Alphabet.split("");
var Crypto = function (alpha, gen, C) {
var p, B, encrypt, decrypt, f, g, modInv, modPow, toAlpha, to10;
toAlpha = function (x) {
var y, p, l, n;
if (x === 0) {
return "!!!!";
}
y = [];
n = 4;
n = Math.ceil(n);
while (n--) {
p = Math.pow(alpha.length, n);
l = Math.floor(x / p);
y.push(alpha[l]);
x -= l * p;
}
y = y.join("");
return y;
};
to10 = function (x) {
var y, p, n;
y = 0;
p = 1;
x = x.split("");
n = x.length;
while (n--) {
y += alpha.indexOf(x[n]) * p;
p *= alpha.length;
}
return y;
};
modInv = function (gen, mod) {
var v, d, u, t, c, q;
v = 1;
d = gen;
t = 1;
c = mod % gen;
u = Math.floor(mod / gen);
while (d > 1) {
q = Math.floor(d / c);
d = d % c;
v = v + q * u;
if (d) {
q = Math.floor(c / d);
c = c % d;
u = u + q * v;
}
}
return d ? v : mod - u;
};
modPow = function (base, exp, mod) {
var c, x;
if (exp === 0) {
return 1;
} else if (exp < 0) {
exp = -exp;
base = modInv(base, mod);
}
c = 1;
while (exp > 0) {
if (exp % 2 === 0) {
base = (base * base) % mod;
exp /= 2;
} else {
c = (c * base) % mod;
exp--;
}
}
return c;
};
p = 91744613;
C = parseInt(C, 10);
if (isNaN(C)) {
C = Math.round(Math.sqrt(Math.random() * Math.random()) * (p - 2) + 2);
}
B = modPow(gen, C, p);
decrypt = function (a) {
var d, x, y;
x = a[1];
y = modPow(a[0], -C, p);
d = (x * y) % p;
d = Math.round(d) % p;
return alpha[d - 2];
};
encrypt = function (key, d) {
var k, a;
k = Math.ceil(Math.sqrt(Math.random() * Math.random()) * 1E10);
d = alpha.indexOf(d) + 2;
a = [];
a[0] = modPow(key[1], k, key[0]);
a[1] = (d * modPow(key[2], k, key[0])) % key[0];
return a;
};
f = function (message, key) {
var n, x, y, w;
y = [];
message = message.split("");
n = message.length;
while (n--) {
x = encrypt(key, message[n]);
y.push(toAlpha(x[0]));
y.push(toAlpha(x[1]));
}
y = y.join("");
return y;
};
g = function (message) {
var n, m, d, x;
m = [];
n = message.length / 8;
while (n--) {
x = message[8 * n + 4];
x += message[8 * n + 5];
x += message[8 * n + 6];
x += message[8 * n + 7];
m.unshift(x);
x = message[8 * n];
x += message[8 * n + 1];
x += message[8 * n + 2];
x += message[8 * n + 3];
m.unshift(x);
}
x = [];
d = [];
n = m.length / 2;
while (n--) {
x[0] = m[2 * n];
x[1] = m[2 * n + 1];
x[0] = to10(x[0]);
x[1] = to10(x[1]);
d.push(decrypt(x));
}
message = d.join("");
return message;
};
return {
pubKey: [p, gen, B],
priKey: C,
decrypt: g,
encrypt: f
};
};
// Usage:
var Alice = Crypto(Alphabet, 69);
var Bob = Crypto(Alphabet, 69);
var message = "Hello!";
console.log(message);
// "Hello!"
message = Alice.encrypt(message, Bob.pubKey);
print(message);
// "Pl)7t&rfGueuL#|)H'P,*<K\.hxw+∆d*`?Io)lg~Adz-6xrR" or something like it.
message = Bob.decrypt(message);
console.log(message);
// "Hello!"
So, basically, Crypto handles all of the Elgamal algorithms, using modPow when it needs to. I think that the modPow function was what you were originally after, wasn't it? The version that you originally posted uses repeated squaring instead of ordinary exponentiation, presumably for purposes of performance, but they're both reasonably speedy.
It still isn't clear to me, though, why you needed a different algorithm for doing "m = a. b ^(p-1-x) mod p". I never needed anything like that in implementing my Elgamal, so I'm not sure what this corresponds to. I did need to implement a function that calculates the modular multiplicative inverse, which I called modInv. Is that what you wanted? I used a stripped-down version of the Extended Euclidean Algorithm to make it.
If it helps, feel free to copy part or all of my code for your project.
And, if you have any more questions about this, please ask me!
EDIT: Note, this code is not intended for actual production-grade encryption. It is really just a proof of concept for the algorithm. With a little work, however, it could be made more secure. Let me know.
EDIT: To encrypt and decrypt text, do the following:
Create a new Crypto object to encrypt the text, and then save it:
var Alice=Crypto(Alphabet, 69);
Here, Alice is just some variable, Alphabet is the 29-symbol alphabet that I defined at the top of the code, and 69 is a primitive root mod 91744613.
Then, create another Crypto object to decrypt the text, and then save it:
var Bob=Crypto(Alphabet, 69);
Although Bob was created in the same way as Alice, they are different objects. Bob cannot decrypt text intended for Alice, and Alice cannot decrypt text intended for Bob.
Now, use Alice's encrypt method to encrypt some text, and save the result:
var codedMessage=Alice.encrypt("HELLO, WORLD.", Bob.pubKey);
Here, message is an empty variable, "HELLO, WORLD." is the text to be encrypted (or the contents of a text file). Bob.key is Bob's public key. We must use Bob's key in the encryption so that Bob (and only Bob) can decrypt the text. The resulting encrypted text will look something like this: "Pl)7t&rfGueuL#|)H'P,*<K\.hxw+∆d*?Io)lg~Adz-6xrR"`. Note that even with the same message, different output will be generated each time. It will still always decrypt to the same value.
Now, in theory, we can send this encrypted text over whatever un-secure channel we want, and no one will be able to decode it. When Bob receives the encrypted text, however, he can decode it. To do this:
var plainMessage=Bob.decrypt(codedMessage);
Now, plainMessage will contain the text "HELLO, WORLD.", which you can read or do whatever you want with.
So, all together, just these four lines will do it:
var Alice=Crypto(Alphabet, 69);
var Bob=Crypto(Alphabet, 69);
var codedMessage=Alice.encrypt("HELLO, WORLD.", Bob.pubKey);
var plainMessage=Bob.decrypt(codedMessage);
// Now, plainMessage contains "HELLO, WORLD."
If you specifically want to do this with text files, then you can either copy-and-paste the contents into the javascript, or you can look into loading the contents of a text file into javascript. To get started, see this SO, and this HG.

convert decimal number to fraction in javascript or closest fraction [duplicate]

This question already has answers here:
How to simplify a decimal into the smallest possible fraction?
(6 answers)
Closed last year.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
So i want to be able to convert any decimal number into fraction. In both forms such as one without remainder like this: 3/5 or with remainder: 3 1/4.
what i was doing is this..
lets say i have number .3435.
Calculate amount of digits after decimals.
multiply by 10 with power of the amount before number.
then somehow find greatest common factor.
Now i don't know how to find GCF. And nor i know how to implement logic to find fraction that represents a number closely or in remainder form if exact fraction doesn't exists.
code i have so far: (testing)
x = 34/35;
a = x - x.toFixed();
tens = (10).pow(a.toString().length - 2);
numerator = tens * x;
denominator = tens;
Your first 2 steps are reasonable.
But what you should do is for the numerator and denominator calculate the Greatest Common Divisor (GCD) and then divide the numerator and denominator with that divisor to get the fraction you want.
GCD is rather easy to calculate. Here is Euclid's algorithm:
var gcd = function(a, b) {
if (!b) return a;
return gcd(b, a % b);
};
Edit
I've added a fully working JSFiddle.
Unless you are willing to work on developing something yourself then I would suggest using a library that someone has already put effort into, like fraction.js
Javascript
var frac = new Fraction(0.3435);
console.log(frac.toString());
Output
687/2000
On jsFiddle
You can use brute force test on different denominators and retain the result that has least error.
The algorithm below is an example of how you might go about this, but, suffers from being inefficient and limited to searching for denominators up to 10000.
function find_rational( value, maxdenom ) {
console.clear();
console.log( "Looking up: " + value );
let best = { numerator: 1, denominator: 1, error: Math.abs(value - 1) }
if ( !maxdenom ) maxdenom = 10000;
for ( let denominator = 1; best.error > 0 && denominator <= maxdenom; denominator++ ) {
let numerator = Math.round( value * denominator );
let error = Math.abs( value - numerator / denominator );
if ( error >= best.error ) continue;
best.numerator = numerator;
best.denominator = denominator;
best.error = error;
console.log( "Intermediate result: "
+ best.numerator + "/" + best.denominator
+ " (" + ( best.numerator/best.denominator)
+ " error " + best.error + " )" );
}
console.log( "Final result: " + JSON.stringify( best ) );
return best;
}
function calc() {
const value = parseFloat( $("#myInput").val() );
if ( isNaN(value) ) {
$( "#myResult" ).val( "NaN" );
return;
}
const rational = find_rational( value, 10000 );
$("#myResult").val( rational.numerator
+ " / " + rational.denominator
+ " ( Error: " + rational.error + " )" );
}
calc();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<P>
Enter a decimal number:<BR/>
<INPUT type="text" name="myInput" id="myInput" value=".3435" onkeyup="calc()"/><BR/>
</P>
<P>
Resulting Rational:<BR/>
<INPUT name="myResult" id="myResult" value=""/><BR/>
</P>
The above determines the .3435 as a fraction is 687 / 2000.
Also, had you gave it PI (e.g. 3.1415926) it produces good looking fractions like 22/7 and 355/113.
One quick and easy way of doing it is
getFraction = (decimal) => {
for(var denominator = 1; (decimal * denominator) % 1 !== 0; denominator++);
return {numerator: decimal * denominator, denominator: denominator};
}
I get very poor results using the GCD approach. I got much better results using an iterative approach.
For example, here is a very crude approach that zeros in on a fraction from a decimal:
function toFraction(x, tolerance) {
if (x == 0) return [0, 1];
if (x < 0) x = -x;
if (!tolerance) tolerance = 0.0001;
var num = 1, den = 1;
function iterate() {
var R = num/den;
if (Math.abs((R-x)/x) < tolerance) return;
if (R < x) num++;
else den++;
iterate();
}
iterate();
return [num, den];
}
The idea is you increment the numerator if you are below the value, and increment the denominator if you are above the value.
Use the Euclidean algorithm to find the greatest common divisor.
function reduce(numerator,denominator){
var gcd = function gcd(a,b){
return b ? gcd(b, a%b) : a;
};
gcd = gcd(numerator,denominator);
return [numerator/gcd, denominator/gcd];
}
This will provide you with the following results on your console
reduce(2,4);
// [1,2]
reduce(13427,3413358);
// [463,117702]
So by continuing from already what you have,
var x = 34/35;
var a = x - x.toFixed();
var tens = Math.pow(10,a.toString().length - 2);
var numerator = tens * x;
var denominator = tens;
reduce(numerator,denominator);
Source: https://stackoverflow.com/a/4652513/1998725
I had researched all over the website and I did combine all code into one, Here you go!
function fra_to_dec(num){
var test=(String(num).split('.')[1] || []).length;
var num=(num*(10**Number(test)))
var den=(10**Number(test))
function reduce(numerator,denominator){
var gcd = function gcd(a,b) {
return b ? gcd(b, a%b) : a;
};
gcd = gcd(numerator,denominator);
return [numerator/gcd, denominator/gcd];
}
return (reduce(num,den)[0]+"/"+reduce(num,den)[1])
}
This code is very easy to use! You can even put number in this function!
The tricky bit is not letting floating points get carried away.
Converting a number to a string restrains the trailing digits,
especially when you have a decimal with an integer, like 1.0625.
You can round off clumsy fractions, by passing a precision parameter.
Often you want to force a rounded value up, so a third parameter can specify that.
(e.g.; If you are using a precision of 1/64, the smallest return for a non-zero number will be 1/64, and not 0.)
Math.gcd= function(a, b){
if(b) return Math.gcd(b, a%b);
return Math.abs(a);
}
Math.fraction= function(n, prec, up){
var s= String(n),
p= s.indexOf('.');
if(p== -1) return s;
var i= Math.floor(n) || '',
dec= s.substring(p),
m= prec || Math.pow(10, dec.length-1),
num= up=== 1? Math.ceil(dec*m): Math.round(dec*m),
den= m,
g= Math.gcd(num, den);
if(den/g==1) return String(i+(num/g));
if(i) i= i+' and ';
return i+ String(num/g)+'/'+String(den/g);
}
Math.roundFraction(.3435,64); value: (String) 11/32
Inspired by #chowey answer, which contained recursive implementation of finding close fraction for a decimal value within given tolerance, here is better (see benchmark), iterative version of it.
function toFractionIterative(x, epsilon = 0.0001) {
if (x == 0) return [0, 1];
const a = Math.abs(x);
let n = 0;
let d = 1;
let r;
while (true) {
r = n / d;
if (Math.abs((r - a) / a) < epsilon) {
break;
}
if (r < a) {
n++;
}
else {
d++;
}
}
return [x < 0 ? -n : n, d];
}
Benchmark (tl;dr: recursive 1,589 ops/s, iterative 5,955 ops/s; use iterative approach)
let v = 3.141592;
document.write(d2f(v)); // 392699/125000
function d2f(v) // decimal to fraction
{
if (Math.floor(v) == v) return v + '/' + 1;
v = Math.abs(v);
let ret = .01, // rounding error tolerance
td = v-Math.floor(v), // trailing digits
r = 1/td, // reciprocal
d = r, // start building denominator
lim = 20; // max loop limit
for (let i = 0; i < lim; i++)
{
td = r-Math.floor(r);
if (Math.abs(r-Math.round(r)) < ret) break;
r = 1/td;
d *= r;
}
return Math.round(d*v) + '/' + Math.round(d);
}
I came up with this for 16ths
function getfract(theNum){
var input=theNum.toString();
var whole = input.split(".")[0];
var rem = input.split(".")[1] * .1;
return(whole + " " + Math.round(rem * 16) + "/16");
}
function decimalToFraction(num) {
let numsAfterDecPoint = num.toString().split('.')[1] ? num.toString().split('.')[1].length : 0;
let numerator = num * Math.pow(10, numsAfterDecPoint);
let denominator = Math.pow(10, numsAfterDecPoint);
console.log(numerator + " / " + denominator)
let d = GCD(numerator,denominator)
return numerator / d + " / " + denominator / d
}
console.log(decimalToFraction(0.5)); // 5 / 10 => 1 / 2
console.log(decimalToFraction(178.45)); // 17845 / 100 => 3569 / 20
function GCD(a,b) {
let r = 0;
while(b != 0) {
r = a % b
a = b;
b = r;
}
return a;
}

How can I move polynomial items in an equation to one side?

So I have a polynomial equation equivalent in js in a string which I can eval. (assuming the eval execution is safe) for example
2 * x + 3 * y - z = 0;
The above is a string and with appropriate scope where x, y and z are defined, I can eval the above string and it will give me the result. I want to make it so that I can find the value of x where others are given. So my desired output would be.
x = (z - 3 * y) / 2;
Is it possible to get the above string? if not then is it possible to just find the value of x when y and z are given? I know this sounds like homework but it isn't.
var x, y, z, r1, r2, a, b,
eq = "2 * x + 3 * y - z = 0;";
console.clear();
eq = eq.replace(" = 0;", "");
y = 12; z = 34;
x = 1; r1 = eval(eq);
x = 2; r2 = eval(eq);
a = r2 - r1; b = r1 - a; x = -b / a;
console.log(x);
Or, if you need the solution formula as a string:
var eq = "2 * x + 3 * y - z = 0;", eq2,
match, a, b, c, x, y, z;
function process(prefix) {
prefix = prefix.replace(/[\s\*]/g, "");
switch (prefix) {
case "" : return +1;
case "+": return +1;
case "-": return -1;
default : return +prefix;
}
}
console.clear();
match = eq.match(/^([^x]*)x([^y]*)y([^z]*)z ?= ?0;$/);
if (match === null || match.length !== 4)
console.log("Invalid equation");
else {
a = process(match[1]);
b = process(match[2]);
c = process(match[3]);
eq2 = "(" + (-b) + " * y + " + (-c) + " * z) / " + a;
console.log(eq2);
y = 12; z = 34;
x = eval(eq2);
console.log(x);
}
eq2 will be (-3 * y + 1 * z) / 2
If I have understood your question correctly,
To find the value of x:
Evaluate the remaining expression, change its sign, and divide it by x's coefficient (if it's not zero).
To get the string array,
Change the sign of each of the remaining coefficients and divide each by x's coefficient.
EDIT: As already suggested,
say b = exp(0,y,z), a = exp(1,0,0).
x = -b/a

Unexpected result when converting decimal to fraction

function gcd(a, b) {
return (b) ? gcd(b, a % b) : a;
}
var dec2Frac = function (d) {
var top = d.toString().replace(/\d+[.]/, '');
var bot = Math.pow(10, top.length);
if (d > 1) {
top = +top + Math.floor(d) * bot;
}
var x = gcd(top, bot);
var r1 = top / x;
var r2 = bot / x;
var frac = r1 + "/" + r2;
var parts = frac.split('/');
var simpler = parts[0][0]+'/'+parts[1][0];
return simpler;
};
If I input 640x960 = 0.66666666666667
I'm expecting the result to be 2/3 as evident here: http://www.mindspring.com/~alanh/fracs.html
Instead this function returns 6/1. Test here: http://jsbin.com/asoxud/1/
As an addition to MvG's Answer,
I found this quite interesting and wanted to understand how floating points are stored and how to get back an fraction of a float to maybe do calculations with them.
It gave a bit of brainache trying to figure this out on my own, but as it made click, i came up with this Fraction function,
I don't know if this helps you or not, but
now that its written anyway , why not leave it here
function Fraction(n, d) {
if ("number" !== typeof n)
throw new TypeError("Excptected Parameter to be of type number");
var strings = n.toString(2).split("."); //Split the number by its decimal point
if (strings.length > 1 && !d) { //No denominator given and n is a float
var floats = [strings[1].substr(0, 27), strings[1].substr(27, 54)]; //Split into to parts
var int64 = [
parseInt(floats[0], 2) << 1,
parseInt(floats[1], 2) << 1
];
var denominator = Math.pow(2, strings[1].length + 1); //
var numerator = int64[0] * Math.pow(2, floats[1].length);
numerator += int64[1];
numerator += parseInt(strings[0], 2) * denominator;
this.numerator = numerator;
this.denominator = denominator;
this.reduce();
this.approx = approx(n);
} else if (strings.length < 2 && !d) { // If no denominator and n is an int
this.numerator = n;
this.denominator = 1;
} else { //if n and d
this.numerator = n;
this.denominator = d;
}
function approx(f, n) {
n = n || 0;
var fraction = new Fraction(1, 1);
var float = Math.pow(f, -1);
var rec = ~~float;
var decimal = float - rec;
if (float.toPrecision(Fraction.precision) == rec)
return new Fraction(1, rec);
var _fraction = approx(decimal, n + 1);
fraction.denominator = rec * _fraction.denominator + _fraction.numerator;
fraction.numerator = _fraction.denominator;
return fraction;
}
}
//The approx precision
Fraction.precision = 10;
Fraction.prototype.toString = function () {
return this.numerator + "/" + this.denominator;
};
Fraction.prototype.gcd = function () {
return (function gcd(u, v) {
return ((u > 0) ? gcd(v % u, u) : v);
})(this.numerator, this.denominator);
};
Fraction.prototype.reduce = function () {
var _gcd = this.gcd();
this.numerator /= _gcd;
this.denominator /= _gcd;
};
Fraction.prototype.valueOf = function () {
return this.numerator / this.denominator;
};
var f = new Fraction(0.3333);
+ f; //0.3333333333
f.toString(); // 6004799502560181/18014398509481984
+ f.approx //0.33333
+ f.approx.toString() //3333/10000
var g = new Fraction(2 / 3);
+ g; //0.6666666666666666
g.toString(); //6004799503160661/9007199254740992
+ g.approx //0.6666666666666666
+ g.approx.toString() //2/3
Heres a JSbin as well
Your floating point numbers are approximations of the rational numbers you hope for. See e.g. Is floating point math broken? for details on this. The upshoot is: you can't hope to actually find a numerator and denominator which represent your original fraction.
If you want that fraction, you should have a look at continued fractions. Each truncated continued fraction will represent the best possible rational approximation for an arbitrary value. You can continue this until the error is sufficiently small.
Here is a page visualizing this approximation. The text is in German, but the maths should be clear enough. This page is in English but doesn't have as much visualization.

Categories

Resources