# Multiplication of Decimal with {float/complex/Fraction}

current scenario -

``````from decimal import Decimal
Decimal('0.5') * 2.1
``````

gives,

``````TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'float'
``````
``````Decimal('0.5') * complex(1 + 2j)
``````

gives,

``````TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'complex'
``````
``````from fractions import Fraction
Decimal('0.5') * Fraction(1, 2)
``````

gives,

``````TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'Fraction'
``````

expected scenario -

1. all three work

note -

1. `Fraction` * {`Fraction`/`float`/`complex`}, `float` * {`complex`/`float`}, `complex` * `complex` are all valid
2. only the `Decimal` type appears to have these invalid multiplications

The documentation for the decimal module does nowhere suggest that the `Decimal` type supports arithmetic operations between `Decimal` and the builtin numeric types, see https://docs.python.org/3/library/decimal.html.

`Decimal` is deliberately inoperable with other non-integer numeric types in many situations due to the high likelihood of surprising results. For example, what would you expect the result of `Decimal('0.1') * 0.1` to be? I would naively expect `Decimal('0.01')`, but if you force things by casting the `float` to `Decimal` (as in `Decimal('0.1') * Decimal(0.1)`, note the lack of quotes in the second term), the result is actually `Decimal('0.01000000000000000055511151231')`. Consider also the difference between `Fraction(1, 3).as_integer_ratio()` and `(Decimal(1) / Decimal(3)).as_integer_ratio()`, and the fact that `Decimal` does not have its own support for the complex plane.

In short, `Decimal` refuses the temptation to guess what you want and instead forces you to deal with the inexact conversion of other types to `Decimal` yourself.

2 Likes

``````Decimal('0.5') * 2.1
Decimal('0.5') * complex(1 + 2j)
Decimal('0.5') * Fraction(1, 2)
``````

Its not enough to say that these should “work” unless you can explain what you mean by “work”.

based on my inspection,

``````print(Fraction(1, 2) * 2.1)
print(Fraction(1, 2) * complex(1 + 2j))
print(Fraction(1, 2) * Fraction(1, 2))
print(Decimal('0.5') * 2)
``````

give,

``````1.05
(0.5+1j)
1/4
1.0
``````

similarly,

``````print(Decimal('0.5') * 2.1)
print(Decimal('0.5') * complex(1 + 2j))
print(Decimal('0.5') * Fraction(1, 2))
``````

should give,

``````1.05
(0.5+1j)
0.25 # or it could be made
# Decimal * Fraction gives 0.25,
# Fraction * Decimal gives 1/4
``````

if we print the output without using print, then,

``````(Fraction(1, 2) * 2.1), (Fraction(1, 2) * complex(1 + 2j)), \
(Fraction(1, 2) * Fraction(1, 2))
``````

gives,

``````(1.05, (0.5+1j), Fraction(1, 4))
``````

and,

``````(Decimal('0.5') * 2)
``````

gives,

``````Decimal('1.0')
``````

similarly,

``````((Decimal('0.5') * 2.1), Decimal('0.5') * Fraction(1, 2))
``````

should give,

``````(Decimal('1.05'), Decimal('0.25'))
``````

plus,

``````Fraction(1, 2) * Decimal('0.5')
``````

should give,

``````Fraction(1, 4)
``````

for complex numbers it appears there is nothing like,

``````Decimal('1.2 + 2.1j')
``````

so,

``````Decimal('0.5') * complex(1 + 2j)
``````

is a bit confusing, but one possibility is to output,

``````(0.5 + 1j)
``````

just like it works for `Fraction`

based on some further inspection, I noted down the types obtained after performing this multiplication for the valid cases,

``````arg1     | arg2     | result
-------------------------------
complex  | complex  | complex
complex  | float    | complex
complex  | Fraction | complex
complex  | int      | complex
Decimal  | Decimal  | Decimal
Decimal  | int      | Decimal
float    | float    | float
float    | Fraction | float
float    | int      | float
Fraction | Fraction | Fraction
Fraction | int      | Fraction
int      | int      | int
``````

just like `float * Fraction` returns an object of type `float`, and `complex * Fraction` returns an object of type `complex`, the same could be true for `{float/complex} * Decimal`