1

I am new to python, I am rewriting program from VBA Excel to Python.

I need accurate calculations but cannot figure out an appropriate way of doing so.

Example:

aa = 0.000016

bb = 0.000016

cc = aa*bb      # which gives 2.5599999999999996e-12

a = decimal.Decimal('0.0000016') 

b = decimal.Decimal('0.0000016')

c = a*b         # which gives 2.56E-12

but when I do :

ccc= aa*b 

It gives me an error

I need a way to either perform math with all Decimal('') numbers or make float numbers more accurate (no additional decimal numbers (0.0016 instead of 0.0015999996))

Lidkaaa
  • 25
  • 1
  • 6
  • 2
    Welcome to Stack Overflow. I would suggest that you include some problematic areas of the code in an edit so that you can create a [Minimal, complete and verifiable example](http://stackoverflow.com/help/mcve). – roganjosh Feb 06 '17 at 20:21
  • try `ccc = aa * float(b)` – Will Feb 08 '17 at 19:21
  • @Will, thank you, but when I do so it gives me the same answers as if I multiplied two floats. Instead I need to figure out a way to keep numbers accurate, without these weird decimals being added at the end. – Lidkaaa Feb 08 '17 at 19:24
  • `VBA Excel` will use floating points as a default as well, so if you are just translating and don't need more accuracy than you already had in Excel, why not just stick with floats? What you are seeing might not be a loss of accuracy when transitioning to Python so much as a different way that values are displayed. In other words, it might just be a formatting artifact. `decimal` is a wonderful module, but it incurs a cost by making arithmetical calculations slower. – John Coleman Feb 08 '17 at 19:38
  • @John Coleman thank you John, I did that, that's pretty much what I have started with. I just transferred the program to python, it ran but the final answers, which had to be 5 of them, gave me inf, #,#,#, nan. Since I got inf, I started checking step by step and comparing to the program in VBA, the numbers got different in the first few calculations, so I assumed its the way Python adds these decimals to the regular numbers. – Lidkaaa Feb 08 '17 at 19:47

2 Answers2

5

You're trying to multiply a float by a decimal.Decimal which throws a TypeError. In order to multiply these, you have to cast one of them so they are the same type and python can determine which type the result should be.

>>> import decimal
>>> d = decimal.Decimal("0.000016")  # d is a Decimal
>>> f = 0.000016                     # f is a float
>>> d*f                              # can't do this!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for *: 'Decimal' and 'float'
>>> float(d) * f                     # cast d to a float, get a float result
2.56e-10
>>> d * decimal.Decimal(f)           # cast f to Decimal, get a Decimal result
Decimal('2.559999999999999884155166274E-10')

Hope this helps! :)

Will
  • 4,299
  • 5
  • 32
  • 50
  • Thank you for your response. It is helpful and I have tried to do it that way as well. It works but what I really need is to find out if there is a way to use floats but still manage how many decimals it uses in calculations. The program that I am converting from VBA uses very small numbers as well as very big numbers and after couple iterations Python gives me inf instead of the answers. As I tried to go step by step to see what kind of thing might cause it I noticed that floats are different in Python and pretty soon they change my calculations to the wrong numbers. – Lidkaaa Feb 08 '17 at 19:42
  • In that case, your solution may be considerably more complex. See the second answer here: http://stackoverflow.com/questions/13479163/round-float-to-x-decimals to read about some of the issues python has with floats. If you're multiplying huge and tiny numbers, and doing so repeatedly, any small rounding error can have a ripple effect you never recover from. You may want to use the `Decimals` instead. Check out the second answer here for more on `Decimals`: http://stackoverflow.com/questions/17470883/how-to-round-to-two-decimal-places-in-python-2-7 – Will Feb 08 '17 at 19:52
  • Thanks a lot! These posts were helpful, but did left me confused on the further steps in my calculations. I have tried to change everything to decimals('') before but then I ran into another problem, such as not being able to use math functions. The program includes matrix inverse and when I change its inputs to decimals it gives me an error for the inverse. – Lidkaaa Feb 08 '17 at 20:10
  • I assume you're using `numpy` for matrix arithmetic? Take a look here, apparently you can specify a data type for your matrix: http://stackoverflow.com/questions/7770870/numpy-array-with-dtype-decimal – Will Feb 08 '17 at 20:17
  • Yes I am using #numpy. I will try to implement that example and see how it works with my program, thank you for all your help. – Lidkaaa Feb 08 '17 at 20:36
0

will was precise in the answer, I had the same problem, the solution was: Convert both values to float type and multiply:

result = float(value1) * float(value2)

Then convert the result to decimal again, and use round to round the number of decimal places:

import decimal

final_result = round(decimal.Decimal(result), 2)
Marcos Paolo
  • 301
  • 2
  • 7