Javascript 舍入问题 - 尝试使用不同的方法获得不同的结果

Javascript rounding issue - trying with different methods with different results

提问人:MistaJase 提问时间:6/8/2023 最后编辑:MistaJase 更新时间:6/8/2023 访问量:26

问:

我知道这个问题以前有人问过,我尝试了多种解决方案都没有成功,而且似乎比看起来更复杂......

我在应用折扣后处理产品价格,因此我将数字四舍五入到小数点后 2 位

所以以这个示例代码为例,希望每个数字都四舍五入,但有时它会四舍五入......

let numbers = []
numbers.push(1.782); 
numbers.push(4.705);
numbers.push(4.715);
numbers.push(4.725);
numbers.push(4.735); 
numbers.push(4.745);
numbers.push(4.755);
numbers.push(4.765);
numbers.push(4.775);
numbers.push(4.785);
numbers.push(4.795);

for (let i=0; i<numbers.length; i++){
  console.log('TEST 1 - num#'+i+ ' ['+numbers[i]+'] toFixed = '+ (numbers[i]).toFixed(2) )
}

function roundToDecimal(num) {
  return Math.round(num * 100) / 100  
}

for (let i=0; i<numbers.length; i++){
  console.log('TEST 2 - num#'+i+ ' ['+numbers[i]+'] roundToDecimal = '+ roundToDecimal(numbers[i]) )
}

返回:

TEST 1 - num#0 [1.782] toFixed = 1.78
TEST 1 - num#1 [4.705] toFixed = 4.71 
TEST 1 - num#2 [4.715] toFixed = 4.71 // wrong
TEST 1 - num#3 [4.725] toFixed = 4.72 // wrong
TEST 1 - num#4 [4.735] toFixed = 4.74
TEST 1 - num#5 [4.745] toFixed = 4.75
TEST 1 - num#6 [4.755] toFixed = 4.75 // wrong
TEST 1 - num#7 [4.765] toFixed = 4.76 // wrong
TEST 1 - num#8 [4.775] toFixed = 4.78
TEST 1 - num#9 [4.785] toFixed = 4.79
TEST 1 - num#10 [4.795] toFixed = 4.79

TEST 2 num#0 [1.782] roundToDecimal = 1.78
TEST 2 num#1 [4.705] roundToDecimal = 4.71
TEST 2 num#2 [4.715] roundToDecimal = 4.72
TEST 2 num#3 [4.725] roundToDecimal = 4.72 // wrong
TEST 2 num#4 [4.735] roundToDecimal = 4.74
TEST 2 num#5 [4.745] roundToDecimal = 4.75
TEST 2 num#6 [4.755] roundToDecimal = 4.76
TEST 2 num#7 [4.765] roundToDecimal = 4.76 // wrong
TEST 2 num#8 [4.775] roundToDecimal = 4.78
TEST 2 num#9 [4.785] roundToDecimal = 4.79
TEST 2 num#10 [4.795] roundToDecimal = 4.8

我知道浮点符号问题......但这太不一致了,我不确定如何进行!

有没有人有可行的解决方案?

JavaScript 浮点

评论

0赞 Eric Postpischil 6/8/2023
没有不一致之处;如果打印数字的完整值,则可以看到原因。简单地说,当十进制数字四舍五入为值时,四舍五入有时是向上的,有时是向下的。4.725 四舍五入到略低于 4.725 的数字,4.715 四舍五入到略高于 4.715 的数字,同样,1/3 四舍五入到略低于 1/3 的数字 (.333),2/3 四舍五入到略高于 (.667) 的数字。所以你的数组中没有 4.715 或 4.725;它的值已四舍五入。NumbernumbersNumbers
0赞 Eric Postpischil 6/8/2023
乘以 100 以获得更多四舍五入会增加更多复杂性。在没有浮点方面的知识的情况下,尝试使用基于二进制的格式处理十进制数是徒劳的。根据你想做什么,你可以保留缩放的数字,比如 4715 而不是 4.715。但是,要获得更完整的解决方案,您需要解释要用这些数字做什么。您所展示的只是打印它们,这很容易。你还需要对这些数字做什么。Number
0赞 MistaJase 6/8/2023
@EricPostpischil - 感谢您的回复...在应用折扣后,我正在处理产品价格
0赞 Eric Postpischil 6/8/2023
以美分为单位,或您使用的任何较小的十进制单位保持价格。在打印之前将它们四舍五入到整数美分。打印时,可以除以 100 并将其打印到小数点后两位。对于所有合理的美元金额(最高数万亿美元),这将四舍五入到所需的十进制数字。请注意,在其他计算中仍可能出现舍入错误,例如计算复利。
0赞 MistaJase 6/8/2023
@EricPostpischil但我的roundToDecimal()不是按照你的建议做的吗?

答: 暂无答案