typescript - 如何将小数转换为最接近的分数
问题描述
我想用一个数字将数字的小数转换为最接近的分数!例如,“8.75”应该是“8 3/4”,“1.875”应该是“1 7/8”,但“8,565217...”不应该显示“8 13/23”而是一个错误。Excel中有一个类似的功能解释here
我也想避免使用像 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/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
这对我来说看起来很合理,尽管我不知道你到底想看到哪些边缘情况。无论如何,希望这会有所帮助。祝你好运!
推荐阅读
- flutter - 通过flutter android安装一个apk
- reactjs - 如何使用 ReactJS 和 AmChart 将数据传递到状态
- javascript - 如何从下拉框中编写一个 For 循环来填充 JSON 文件中的第二个下拉框?
- git - 壁球历史但保留 X 个最近的提交
- sql - Micorosft Access SQL - 计算 3 个相关表中的外键记录数
- c++ - 了解虚拟派生类的大小
- python - 如何在计算验证指标之前编写自定义 Keras 验证以对多个图像切片进行平均预测
- angular - NGX-MQTT | 蚊子
- java - Maven(exec plugin) 不使用“/”字符解析项目路径
- ssis - 添加新的转换列失败