DIY四舍五入功能给出奇怪的值[重复]

DIY rounding function gives weird values [duplicate]

提问人:1cedsoda 提问时间:1/10/2021 最后编辑:Jonathan Hall1cedsoda 更新时间:1/10/2021 访问量:171

问:

我已经对这个简单的函数进行了编码,以将双精度四舍五入到自定义步长。 普通的 .round() 函数会重新调整 int,并且只能四舍五入到最接近的 1。 我的函数返回一个双精度,可以四舍五入到最接近的 100.0、5.0、1.0、0.1 或 0.23,你明白了。

但是当我投入某些双打时,结果并没有真正奏效,而且差距很小。

我认为这与计算机如何进行浮动逗号计算有关,但我需要一种有效的方法来解决这个问题。

在DartPad上运行

void main() {
  stepround(61.337551616741315, 0.1); // this should be 61.3 but is 61.300000000000004
}

/// rounds a double with given steps/precision
double stepround(double value, double steps) {
  double rounded = (value / steps).round() * steps;
  print(value.toString() + " rounded to the nearest " + steps.toString() + " is " + rounded.toString());
  return rounded;
}

颤振 飞镖 舍入 浮动精度

评论

0赞 julemand101 1/10/2021
请参见:stackoverflow.com/a/60655897/1953515
1赞 jamesdlin 1/10/2021
这回答了你的问题吗?浮点数学坏了吗?
1赞 jamesdlin 1/10/2021
至于如何解决它:无论你使用什么基数,总会有无法准确表示的实数。您可以尝试使用避免,而是使用 package:decimal,这至少会更好地匹配您关于哪些数字是可表示的心智模型。double

答:

0赞 Mohammad Kurjieh 1/10/2021 #1

正如评论中提到的,这个问题的原因是计算机处理浮点数的方式。请参阅评论中的链接以获取进一步说明。

然而,简而言之,问题主要是在将小数点除以小数点或将小数点相乘时引起的。因此,我们可以创建一个与您创建的方法类似的方法,但使用不同的方法。我们将精度取为 int。

即:0.1 => 10;0.001 => 1000

double stepround(double value, int place){
   return (value * place).round() / place; 
}

// This will return 61.3
stepround(61.337551616741315, 10);

// This will return 61.34
stepround(61.337551616741315, 100);

// This will return 61.338
stepround(61.337551616741315, 1000);

此方法有效,因为由乘法引起的小部分被 删除。在那之后,我们正在做一个整数的除法,这不会产生这样的问题。round()