-1

I am generating an array, which contains very similar but not equal values, due to float inaccuracies. Here are sample elements from the beginning of the array:

[1.6666666666651508, 1.6666666666651508, -0.9999999999990905, -0.6666666666660604, 1.6666666666651504, 0.0, 0.0, -1.6666666666651513, 0.0, 0.0, 0.0, 1.6666666666651493, 0.0, 1.6666666666651493, 1.6666666666697005, 3.3333333333302986, 3.333333333334846, 3.3333333333348536, 3.3333333333302986,...]

I want to slice these numbers at a fixed position to remove these (it is essential for my code in a bigger context, that those inaccuracies do not occur). I've tried to bitmask it with 0b111.1111111 (= 7.9921875), but apparantely python doesn't support the & on floats. I've tried to shift them, convert them to integers and then to use &, but I just can't get it done.

Now, I was wondering, if there is an easy way to bitmask floats, or if there is another way in python, to slice floats after a specific position or to fix this.

Lavair
  • 888
  • 10
  • 21
  • 3
    Use [`decimal.Decimal`](https://docs.python.org/3/library/decimal.html#decimal.Decimal) ? That type can represent decimals exactly, unlike `float`. – jkr Jul 22 '20 at 15:25
  • `Fraction`s are accurate, `Decimal` just has higher accuracy than `float` – Azat Ibrakov Jul 22 '20 at 15:33
  • Also, in case you are using 32-bit python or 32-bit floats you can gain some more accuracy by switching to 64-bit. – Niko Föhr Jul 22 '20 at 15:35
  • @np8: 32-bit floating-point would be unable to present the values shown, such as 1.6666666666651508 and 1.6666666666651493. – Eric Postpischil Jul 23 '20 at 09:56

1 Answers1

0

One way, although lessening accuracy slightly, is to round it. For example, use this:

i = 5/3
print(i)
i = round(i, 10)
print(i)

This might print this:

1.66666666666692
1.66666666666
cs1349459
  • 911
  • 9
  • 27
  • This merely conceals the problem. It does not correct it but instead leaves a harder-to-find problem. This is because, unless the program has some decimal pattern in the numbers it is working with (which is not present in the example numbers shown), we can expect no correlation between the computed floating-point values and the decimal rounding points induced by `round`. When two numbers fall on different sides of one of those rounding points, `round(i, 10)` will produce different results, so this “solution” fails. However, that might occur infrequently enough to be missed in testing. – Eric Postpischil Jul 23 '20 at 10:05
  • For example, there are 10^10 points where the rounding of `round(i, 10)` changes between 1 and 2. Two of the sample numbers that apparently are desired to be the same differ by 20497 ULP. There are 2^52 ULP between 1 and 2. So in approximately 20497•10^10/2^52 cases like this, the difference would span a rounding point. That is 4.55%. So we would not expect the problem to be revealed in a test such as one producing the sample results OP showed. – Eric Postpischil Jul 23 '20 at 10:09
  • @EricPostpischil as far as i understood your concerns your issue with the solution is, that for example `round(1.66666655,7) (=1.6666665)` and `round(1.66666656,7) (= 1.6666666)` would produce different results? If that's the only issue, that would be fine in my case, because the inaccuracies occur almost never before the 10th digit and im rounding after the third or fourth already. But in general, do you have a more general solution in mind to avoid this issue? – Lavair Jul 24 '20 at 17:40
  • 1
    @Lavair: There is no general solution, and there cannot be. Floating-point arithmetic was **designed** to approximate real arithmetic. That is stated in the IEEE-754 standard for floating-point arithmetic. For the most part, floating-point arithmetic should not be used when you want exact results. Using it for exact results requires expertise and is situation-dependent. You would have to explain in the question specifically what you are doing and why you need equal results. Depending on the situation, the solution might be to use something other than floating-point or using another algorithm. – Eric Postpischil Jul 24 '20 at 17:47