【发布时间】:2021-11-08 23:04:30
【问题描述】:
我想将一个连续范围的双精度值 [10.0,20.0] 映射到 [100,200] 范围内的一个字节;
以下内容必须适用(即使来回转换多次):
convertToByte(convertToDouble(y)) == y
谢谢。
【问题讨论】:
-
你知道 (20 - 10) / (200 - 100)(相当于 1/10)不能用 Dart 用于
double的格式表示吗?它将四舍五入为 0.1000000000000000055511151231257827021181583404541015625。另一方面,当它的倍数与 10 相加时,其中一些将高于目标(10.1、10.2、10.3 等),而另一些将低于目标。例如,对于 3 个步骤,结果将是 10.300000000000000710542735760100185871124267578125。你真的希望它映射到 102,即使它通过了 10.3? -
我知道它会被四舍五入。你提到的正是问题所在。我对另一个“映射逻辑”持开放态度,只要它始终将相同的值映射到特定的字节,并且在多次来回转换它们时,给出相同的可预测结果。
-
你希望它如何四舍五入?只考虑
convertToByte(double n) => (n * 10).round(); -
这是合适的。但最终数字会发生变化,因此因子不会是 10,而是
6/95。当我多次来回转换它们时,有些值没有正确映射。 -
所以你想将任意范围的双精度 a..b 映射到一个字节范围 c..d。我可能会尝试
convertToByte(double x) { var r = d - c; return c + (r * x - r * a)/(b-a).round(); }。由于d-c是一个相对较小的整数,r是一个精确值,具有结果的近似大小。这至少应该最大限度地减少舍入误差。
标签: dart mapping rounding precision floating-accuracy