Infinite fraction: 1/3, 2/3, pie, etc.
Non-infinite fractions: 1/2, 1/5, 1/10, etc.
How can I detect when a a number is an infinitely fraction?
CodePudding user response:
Interesting question.
Carefully following the wisdom laid out in this question on math.stackexchange.com, I think the following should do the trick for an irreducible fraction:
function* primeFactors(n) {
let divisor = 2;
while (n >= 2) {
if (n % divisor == 0) {
yield divisor;
n = n / divisor;
} else {
divisor ;
}
}
}
const isRepeating = (n, d) => {
const fn = n % d;
if (fn === 0) {
return false;
}
return !Array.from(primeFactors(d)).every(v => v === 2 || v === 5)
}
So, how to reduce a fraction? If you factorize the numerator and the denominator, you can figure out which factors they have in common, then divide both numerator and denominator by these common factors. Here's one way of doing this:
const counts = (arr) => {
return arr.reduce((acc, curr) => {
const currentCount = acc.get(curr) ?? 0;
acc.set(curr, currentCount 1)
return acc;
}, new Map())
}
const reduceFraction = (n, d) => {
const fn = Array.from(primeFactors(n));
const fd = Array.from(primeFactors(d));
const countsFn = counts(fn);
const countsFd = counts(fd);
let rn = n;
let rd = d;
countsFn.forEach((count, factor) => {
const fdCount = countsFd.get(factor) ?? 0;
const c = Math.min(fdCount, count);
for (let i = 0; i < c; i) {
rn /= factor;
rd /= factor;
}
})
return { n: rn, d: rd }
}
So, putting this all together:
function* primeFactors(n) {
let divisor = 2;
while (n >= 2) {
if (n % divisor === 0) {
yield divisor;
n = n / divisor;
} else {
divisor ;
}
}
}
const counts = (arr) => {
return arr.reduce((acc, curr) => {
var _a;
const currentCount = acc.get(curr) ?? 0;
acc.set(curr, currentCount 1);
return acc;
}, new Map());
};
const reduceFraction = (n, d) => {
const fn = Array.from(primeFactors(n));
const fd = Array.from(primeFactors(d));
const countsFn = counts(fn);
const countsFd = counts(fd);
let rn = n;
let rd = d;
countsFn.forEach((count, factor) => {
var _a;
const fdCount = countsFd.get(factor) ?? 0;
const c = Math.min(fdCount, count);
for (let i = 0; i < c; i) {
rn /= factor;
rd /= factor;
}
});
return {
n: rn,
d: rd
};
};
const isRepeating = (num, den) => {
const {
n,
d
} = reduceFraction(num, den);
const fn = n % d;
if (fn === 0) {
return false;
}
return !Array.from(primeFactors(d)).every(v => v === 2 || v === 5);
};
console.log(isRepeating(4, 3))
console.log(isRepeating(1, 140))
console.log(isRepeating(1, 2))
console.log(isRepeating(2, 50))
console.log(isRepeating(3, 15))
However, be aware that sometimes (due to floating-point stuff), JS might not agree.
const a = 0.1;
let t = 0;
for (let i = 0; i < 10; i) {
t = a;
}
console.log(t)
CodePudding user response:
You can detect the maximum length of 32-bit float number after-comma section. Then by getting the number devided, split the number by '.' and get the after-comma period length. if it is the same or length - 1, it is probably infinite fraction
CodePudding user response:
You can use isFinite() function provided by JavaScript.