-1

i want to map a continuous range of double values [10.0,20.0] to a byte in the range of [100,200];

The following must apply (even when converting back and forth multiple times):

convertToByte(convertToDouble(y)) == y

Thanks.

zel873ju
  • 139
  • 2
  • 7
  • Are you aware that (20 - 10) / (200 - 100) (equivalently, 1/10) is not representable in the format Dart uses for `double`? It will be rounded to 0.1000000000000000055511151231257827021181583404541015625. On the other hand, when multiples of that are added to 10, some of them will be above the targets (10.1, 10.2, 10.3, and so on) and some will be below. E.g., for 3 steps, the result will be 10.300000000000000710542735760100185871124267578125. Do you really want that mapped to 102, even though it passed 10.3? – Eric Postpischil Sep 13 '21 at 17:01
  • I'm aware that it will be rounded. What you mention is exactly the problem. I'm open for another 'mapping logic' as long as it is consistently mapping the same values to a specific byte and also when converting them back and forth multiple times, giving the same predictable result. – zel873ju Sep 13 '21 at 18:46
  • 1
    How do you want it rounded? Consider just `convertToByte(double n) => (n * 10).round();` – lrn Sep 13 '21 at 20:14
  • This would be suitable. But in the end the numbers are changing, so the factor wouldn't be 10 but ```6/95```. And some values are not mapped correctly, when i'm converting them back and forth multiple times. – zel873ju Sep 13 '21 at 21:07
  • Related questions are [here](https://stackoverflow.com/questions/20883498/rounding-in-c-and-round-tripping-numbers/20884240#20884240) and [here](https://stackoverflow.com/questions/44623331/does-a-floating-point-reciprocal-always-round-trip). Simple multiplication and division will not generally preserve value. The question is how to “fix” that. – Eric Postpischil Sep 13 '21 at 23:59
  • 1
    So you want to map an arbitrary range of doubles a..b to a range of bytes c..d. I'd probably just try `convertToByte(double x) { var r = d - c; return c + (r * x - r * a)/(b-a).round(); }`. Since `d-c` is a relatively small integer, `r` is an exact value which has the approximate size of the result. That should at least minimize rounding errors. – lrn Sep 14 '21 at 09:55

1 Answers1

0

With help of the comments to the question we're using the following code:

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);
  }

This does not provide a solution for the specified test, but a deterministic answer for a specific value. When converting a byte back to a value and vice versa multiple times the output always stays the same. This is what we needed for our application.

zel873ju
  • 139
  • 2
  • 7
  • 1
    You should update the question to state the criteria: convertToByte(convertToDouble(y)) = y was required, but the test cases shown in the question were not. – Eric Postpischil Sep 15 '21 at 11:04