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