【问题标题】:Convert a continuous range of doubles to a discrete int range将连续的双精度范围转换为离散的 int 范围
【发布时间】: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


【解决方案1】:

在 cmets 的帮助下,我们正在使用以下代码:

int convertToByte(
    double initial,
    double minValue,
    double maxValue,
    int minByte,
    int maxByte,
  ) {
    double value = initial - minValue;
    double valueRange = maxValue - minValue;
    int byteRange = maxByte - minByte;
    double valueSteps = valueRange / byteRange;
    double byte = (value / valueSteps);
    return (minByte + byte.round()).clamp(minByte, maxByte);
  }

为指定测试提供解决方案,而是为特定值提供确定性答案。 将一个字节转换回一个值(反之亦然)多次时,输出始终保持不变。 这是我们的应用程序所需要的。

【讨论】:

  • 您应该更新问题以说明标准:convertToByte(convertToDouble(y)) = y 是必需的,但问题中显示的测试用例不是。
猜你喜欢
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 2022-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多