how to identify periods in decimals of bignumbers
Hello, maybe a stupid question, but is there a natural way to get periodicity in BigNumbers decimals
math.config({
number: 'BigNumber', // Default type of number:
// 'number' (default), 'BigNumber', or 'Fraction'
precision: 20 // Number of significant digits for BigNumbers
})
math.divide(math.bignumber(1),math.bignumber(6)).toFixed();
'0.16666666666666666667'
as you can see it ends with digit '7'
I wish to identify here a period of length 1 starting at decimal 2 : '0.1 ͞6'
thx
You can use fractions for that, like:"
math.fraction(1, 6).toString() // "0.1(6)"
math.fraction(1, 7).toString() // "0.(142857)"
EDIT: Fractions cannot work with BigNumber though, you'll have to calculate with fractions from the start.
thank you very much !! another stupid question... sorry... if I start from a string formula, which tools are available to get decimal period ? is there really only by fraction that I could achieve this ?
math.config({
number: 'Fraction'
})
math.simplify('cos(pi/n)'.replace(/n/g, 3),{},{exactFraction:true}).toString()
'cos(pi / 3)'
math.simplify('1/n'.replace(/n/g, 3),{},{exactFraction:true}).toString()
'1 / 3'
I wish I could from whatever str formula find the decimal period
@nycos62 , if you know limits on the denominator and numerator , you can use method from https://stackoverflow.com/questions/14002113/how-to-simplify-a-decimal-into-the-smallest-possible-fraction/14011299#14011299 to convert decimal to fraction, then use fraction to string as @josdejong says
p.s. perhaps, can you just work with fractions all the time?
You can use math.fraction(value).toString().
You should be aware though that the representation may not be exact, for example you may have a value like 0.3333333333, then the question is is this the exact number, or is it a rounded representation of 1/3 and should it have an infinite number or digits? So, be careful with the precision you need to work with.
I might have found some sort of middle solution...
math.config({
number: 'BigNumber', // Default type of number:
// 'number' (default), 'BigNumber', or 'Fraction'
precision: 509 // Number of significant digits for BigNumbers
})
const a = math.bignumber("205.16666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666667");
const b = math.bignumber("185.85714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714285714286");
const c = math.bignumber("19.129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258064516129032258065");
const d = math.bignumber("26.708333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333");
const e = math.bignumber("53.071428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571");
function findLongestSubstring (str) {
let candidate = "";
for (let i = 1; i <= str.length - i; i++) {
if (str.indexOf(str.substring(0, i), i) === i)
candidate = str.substring(0, i);
}
return candidate;
}
function rotateAndMoveLeft (str, substr, fromIndex) {
const rotate = (str) => `${str[str.length-1]}${str.slice(0, str.length-1)}`;
const lastIndex = substr.length - 1;
let rotatedStr = substr;
let pos;
// console.log(`str=${str}, substr=${substr}, fromIndex=${fromIndex}`);
for (pos = fromIndex - 1; pos >= 0; pos--) {
if (rotatedStr[lastIndex] === str[pos]) {
rotatedStr = rotate(rotatedStr);
} else {
pos++;
break;
}
}
const from = pos !== -1 ? pos : 0;
return {
subStr: rotatedStr,
from,
numMoved: fromIndex - from
};
}
function shrinkPattern (pattern) {
const _shrink = (head, tail) => {
if (tail.length === 0)
return head;
return tail.split(head).every(item => item.length === 0) ?
head : _shrink(`${head}${tail[0]}`, tail.slice(1));
}
return _shrink(pattern[0], pattern.slice(1));
}
function testRepeatingDigits (num) {
const str = num.toString().substring(0,num.toString().length-3);
const idx = str.indexOf('.');
if (idx < 0)
return false;
const digitStr = str.substring(idx + 1);
const [...digits] = digitStr;
// the first guess of repeating pattern from the right-most digit
const init = [...findLongestSubstring(digits.slice(0).reverse().join(''))].reverse().join('');
// no repeating patterns found
if (init.length === 0)
return {
result: (Math.round(num * 100) / 100).toString(),
pattern: "None"
};
// rotate the first guessed pattern to the left to find the beginning of the repeats
const searchFrom = digitStr.length - (init.length * 2);
const { subStr, from, numMoved } = searchFrom > 0 ?
rotateAndMoveLeft(digitStr, init, searchFrom) : { subStr: init, from: 0, numMoved: 0 };
// shrink the pattern to minimum
const pattern = shrinkPattern(subStr);
// truncate the digits overflows the two repeatings of the pattern
return {
result: `${str.substring(0, idx+1)}${digitStr.substring(0, from + pattern.length * 2)}...`,
pattern
};
}
function toStringVinculum(n) {
let test = testRepeatingDigits(n);
let overlineChar = '\u0305';//not compatible on android :/ , so usage of span
let nStr = n.toString();
if (test == false || test.pattern == 'None')
return n.toString();
else
{
return test.result.substring(0,test.result.length-(3+(2*test.pattern.length))) + '<span style="text-decoration:overline">' +test.pattern.split('').join('</span><span style="text-decoration:overline">') + '</span>';
}
}
console.log(toStringVinculum(a));
console.log(toStringVinculum(b));
console.log(toStringVinculum(c));
console.log(toStringVinculum(d));
console.log(toStringVinculum(e));
'205.1‾6'
'185.‾857142'
'19.‾129032258064516'
'26.708‾3'
'53.0‾714285'