如何将小数转换为最接近的分数



我想将数字的小数转换为最接近的分数! 例如,"8.75"应为"8 3/4","1.875"应为"1 7/8",但"8,565217..."不应显示"8 13/23",而应显示错误。 这里解释了Excel中的类似功能

我也想避免使用像 fraction.js 这样的第三个库,而更喜欢使用本机 JS/TS 或 Lodash!有人有想法吗?=)

感谢您的帮助!

编辑: 我尝试了一部分代码,但没有按预期工作 cs 8.75 给我发送 35/4 和没有 8 3/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));
}

好吧,我不确定这是否正是您想要的,但它应该希望能为您提供一些有关如何进行的想法:

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/53.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

这对我来说看起来很合理,尽管我不知道你到底想看到一些边缘情况。 无论如何,希望有帮助。 祝你好运!

最新更新