Javascript(浮点问题):有没有可靠的方法将分数转换成小数,然后再转换回来?
假设我有一个非常简单的分数(为了这个问题的目的,假设所有讨论的案例都是Javascript(浮点问题):有没有可靠的方法将分数转换成小数,然后再转换回来?,javascript,math,floating-point,data-conversion,fractions,Javascript,Math,Floating Point,Data Conversion,Fractions,假设我有一个非常简单的分数(为了这个问题的目的,假设所有讨论的案例都是0
0<[VALUE]<1
;也就是说:与8 7/16
或1.625
不同):
我的起始分数:
someFraction='1/3';//结果:字符串值包含“1/3”
好的,很容易把它转换成十进制:
对应的decimal=eval(someFraction);//结果:浮点值包含0.3333
(是的,是的,eval
的邪恶以及所有这些。请与我一起工作;这是一个例子)
现在,假设我想再次将其返回到“1/3”
。如果这是1/4(0.25)
,则没有问题:
我们想要一个简单的最大公分母函数(将结果简化为可管理性),比如
…然后我们就可以取出测试字符串的小数部分:
let justDecimalPart = ('' + 0.25).slice(2);
乘以它的长度幂,我们的分子和分母就会减少:
let commonFactor = Math.pow(10,justDecimalPart.length); // Result: 100
// = 25 = 100
reduce((justDecimalPart * commonFactor), commonFactor); // Result: 1/4
…太棒了!结果很好
编辑:一时兴起,我对十进制值尝试了相同的reduce函数,但没有将它们相乘(reduce(0.25,1);//结果:“1/4”
)。抱歉;大脑放屁。忽略上面的指数位☺️
…但是1/3
是一个重复的小数点。如果我们执行相同的步骤,我们会得到3333/1000000000000000
(((1/3)*1e16)+'/'+1e16
),而17/29
更糟糕
从1/3
跳槽后,有没有办法回到的“1/3”
编辑:我不是想达到无限精度,只是想达到可管理的精度,最好是通过限制小数长度,然后四舍五入/简化结果
这里的用例示例:我正在使用木工计算器。25毫米,用美国通用单位表示(精确到小数点后3位),与63/64相同。我似乎只能达到125/128
(25/25.4).toPrecision(3) = 0.984
(63/64).toPrecision(3) = 0.984
似乎我在转换过程中遗漏了一个步骤;我没有将小数乘以分母的结果四舍五入:
decimalValue = (63 / 64).toPrecision(3); // Result: 0.984
denominator = 128;
numerator = decimalValue * denominator; // Result: 125.952
numerator = Math.round(numerator); // Result: 126
reduce(numerator, denominator); // Result: 63/64
不,没有,它与javascript无关,那只是数学。你不能准确地将1/3表示为十进制,你只能表示它的估计值。不,我明白了。我希望有人能有一个巧妙的技巧来抵消/减少数字,以达到相同的点。我不想让这项工作达到无限精度,仅为1/128左右。您在问题中自己说出来,最终得到的结果是
3333333/100000000000000
。唯一的方法是限制转换中分子/分母的大小。这将降低从小数到小数的转换精度,但更可能使您的结果接近w你想要什么。对,这就是我希望在这里得到的,以及为什么包含的reduce函数保持一个单独的分子和分母。如果我取一个值。比如说,toPrecision(3)
,然后在减少之前对转换进行四舍五入…你刚刚发现(一个众所周知的事实)一些有理数没有有限的十进制展开式。因此,如果你使用这种展开式,你无法表达所有的有理数。解决方法是永远不要在第一位进行展开(即除法)。这就是为什么我们首先需要有理数的“库”(例如,允许我们将0.33…表示为1/3),否则,我们只需使用浮点数,让编译器计算出表达式1/3或类似表达式的浮点数。
decimalValue = (63 / 64).toPrecision(3); // Result: 0.984
denominator = 128;
numerator = decimalValue * denominator; // Result: 125.952
numerator = Math.round(numerator); // Result: 126
reduce(numerator, denominator); // Result: 63/64