我想将数字的十进制转换为一个数字最接近的分数! 例如,“ 8.75”应为“ 8 3/4”,“ 1.875”应为“ 1 7/8”,但“ 8,565217 ...”不应显示“ 8 13/23”,而是错误。 Excel here
中有类似的功能我也想避免使用第三个lib之类的fraction.js,而是更喜欢使用本机JS / TS或Lodash!有人有主意吗? =)
谢谢您的帮助!
编辑: 我尝试了一部分代码,但无法正常工作。CS 8.75给我发送了35/4,而没有发送给我83/4 ......
private checkNumberToCompute(numberToCompute: any) {
let numberToReturn = numberToCompute;
if (
(!isNaN(Number(numberToCompute)) && numberToCompute.includes('.')) ||
(numberToCompute.includes(',') && !numberToCompute.includes('/'))
) {
console.log('Nombre à décimal sans fraction');
numberToReturn = this.computeFractions(numberToCompute);
}
return numberToReturn;
}
private computeFractions(numberToCompute: any): string {
console.log('numberToCompute', numberToCompute);
const lenghtOfDecimals = numberToCompute.substring(numberToCompute.indexOf('.') + 1).length;
let denominator = Math.pow(10, lenghtOfDecimals),
numerator = numberToCompute * denominator;
const divisor = this.gcd(numerator, denominator);
numerator /= divisor;
denominator /= divisor;
return Math.floor(numerator) + '/' + Math.floor(denominator);
}
private gcd(numerator: number, denominator: number): any {
if (denominator < 0.0000001) {
return numerator;
}
return this.gcd(denominator, Math.floor(numerator % denominator));
}
答案 0 :(得分:3)
好吧,我不确定这是否正是您想要的,但希望它能给您一些有关如何进行的想法:
const acceptableDenominators = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const maxDistanceToNumerator = 0.0001;
function numberToFractionString(n: number): string | undefined {
const negative = (n < 0);
if (negative) n = -n;
const wholePart = Math.floor(n);
n -= wholePart;
const denom = acceptableDenominators.find(d =>
Math.abs(d * n - Math.round(d * n)) <= maxDistanceToNumerator
);
if (typeof denom === 'undefined') {
return;
}
const numer = Math.round(denom * n);
if (denom === 1) {
return "" + (wholePart + numer) * (negative ? -1 : 1);
}
return (negative ? "-" : "") +
(wholePart ? wholePart + " " : "") +
numer + "/" + denom;
}
这个想法是,您需要弄清楚分数的可接受的分母是什么;在您的情况下,您似乎只需要一个数字,所以这就是我仅指定1
-9
的原因。另外,您需要弄清楚浮点数必须与小数之间的接近程度才能接受它。在这种情况下,我已指定要被识别为3/5
的事物,它必须在2.9999/5
和3.0001/5
之间。
然后有很多边缘情况要处理(负数和非常接近整数的数字很有趣),但是主要步骤是只检查每个可能的分母从最低到最高(自动给您减少的分数,因为它将在4/8之前找到1/2)并选择第一个分子足以接近整数的分子...或返回undefined
(而不是抛出错误,但是如果您想要的话)。
让我们看看它是否有效:
const tests = [8.75, 1.875, 8.565217, 9.99999999, -1, -0.888889,
0, 1e140, -1e-140, -0.111111, 0.5,
-7.66667, -7.6667, -7.667, -7.67, -7.7,
NaN, Infinity, -Infinity];
tests.forEach(n =>
console.log("" + n + ": " + String(numberToFractionString(n)))
);
// 8.75: 8 3/4
// 1.875: 1 7/8
// 8.565217: undefined
// 9.99999999: 10
// -1: -1
// -0.888889: -8/9
// 0: 0
// 1e+140: 1e+140
// -1e-140: 0
// -0.111111: -1/9
// 0.5: 1/2
// -7.66667: -7 2/3
// -7.6667: -7 2/3
// -7.667: undefined
// -7.67: undefined
// -7.7: undefined
// NaN: undefined
// Infinity: undefined
// -Infinity: undefined
在我看来,这是合理的,尽管我不知道您对于某些极端情况到底希望看到什么。无论如何,希望能有所帮助。祝你好运!