0

I have a list of Base Resistor Values

BaseRes=[1.0,1.1,1.2,1.3,1.5,1.6,1.8,2.0,2.2,2.4,2.7,3.0,3.3,3.6,3.9,4.3,4.7,5.1,5.6,6.2,6.8,7.5,8.2,9.1]

I then want to make a list containing these base values and those values multiplied by 10:

Resistors = BaseRes
Resistors = Resistors+[res*10 for res in BaseRes]

output:

Resistors
[1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 47.0, 51.0, 56.0, 62.0, 68.0, 75.0, 82.0, 91.0]

As you can see this works fine for me. However when I want to add the list of the base resistor values multiplied by 100 I get some odd values for a few of the values:

Resistors = Resistors+[res*100 for res in BaseRes]

output:

 Resistors
[1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 2.0, 2.2, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 6.2, 6.8, 7.5, 8.2, 9.1, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 18.0, 20.0, 22.0, 24.0, 27.0, 30.0, 33.0, 36.0, 39.0, 43.0, 47.0, 51.0, 56.0, 62.0, 68.0, 75.0, 82.0, 91.0, 100.0, 110.00000000000001, 120.0, 130.0, 150.0, 160.0, 180.0, 200.0, 220.00000000000003, 240.0, 270.0, 300.0, 330.0, 360.0, 390.0, 430.0, 470.0, 509.99999999999994, 560.0, 620.0, 680.0, 750.0, 819.9999999999999, 910.0]

mainly the 110 value, the 220 value, the 510 value and the 820 value are confusing me.

I do not understand what is going on here.

Any help would be greatly appreciated

Jesse
  • 901
  • 1
  • 9
  • 25
  • 1
    That's floating-point arithmetic for you, and many people are commonly confused by it. I'm certain this is a duplicate; just a moment. – icktoofay Oct 21 '13 at 01:35
  • 2
    Read [Floating Point Arithmetic: Issues and Limitations](http://docs.python.org/2/tutorial/floatingpoint.html) – Yohann Oct 21 '13 at 01:36
  • That is how **floating point arithmetic** works. Look it up. – OdraEncoded Oct 21 '13 at 01:36

2 Answers2

3

While it is true that what you're seeing is rounding errors in floating-point representations, you're probably here for a fix. I'd recommend Python's decimal module, which is designed to handle situations where you need precise, human math and not fast binary approximations.

from decimal import *
getcontext().prec = 3
resBase = [Decimal(x) for x in [1.0, 1.1, 1.2, 1.3, 1.5, 1.6, 1.8, 
    2.0, 2.2, 2.4, 2.7, 3.0, 3.3, 3.6, 3.9, 4.3, 4.7, 5.1, 5.6, 
    6.2, 6.8, 7.5, 8.2, 9.1]]
print [res * 100 for res in resBase]

Output:

[Decimal('100'), Decimal('110'), Decimal('120'), Decimal('130'), Decimal('150'), 
Decimal('160'), Decimal('180'), Decimal('200'), Decimal('220'), Decimal('240'), 
Decimal('270'), Decimal('300'), Decimal('330'), Decimal('360'), Decimal('390'), 
Decimal('430'), Decimal('470'), Decimal('510'), Decimal('560'), Decimal('620'), 
Decimal('680'), Decimal('750'), Decimal('820'), Decimal('910')]
Mike DeSimone
  • 41,631
  • 10
  • 72
  • 96
  • I didn't know about the decimal module. Thank you. – Christian Ternus Oct 21 '13 at 02:26
  • I only found out about it because I was researching how to do something similar, namely store electronic component values in a database without precision loss, and using a numeric format as opposed to string so sorts and filters work right. I've seen capacitors span the range from single picofarads to almost ten farads, a thirteen decade range. Also, lots of useful numbers (like 1.1) don't come out even when expressed in binary. Anyway, Django maps the database representation to `Decimal`, which is how I found out. – Mike DeSimone Oct 21 '13 at 05:28
  • I was unaware of the decimal module as well, Thank you – Jesse Oct 21 '13 at 10:26
0

As others have pointed out, this is a floating-point issue. You're probably wondering how to fix it, though.

Try something like:

import math
Resistors = Resistors+[math.floor(res*100) for res in BaseRes]

I recommend reading the documentation for Python's math package for more information and some useful functions that can really help out. Happy coding!

Christian Ternus
  • 8,406
  • 24
  • 39