Don’t test two seperate conversions at the same time. What is going wrong here is the step _amount → _value, not _value → bytes. _value isn’t 205, it’s 204 because of how floating point numbers work.
round would be better to use here than int, as floating-point errors shouldn’t be large enough to affect rounding to the nearest integer. (int itself does not round a floating-point number, but simply takes the integer portion, i.e. drops the fractional part.)
Depending on your inputs, there is one thing to be aware of with round: it uses “banker’s rounding”, where a result is rounded to the nearest even integer if the argument is half-way in between:
The right way is to create a system that preserves the necessary integer value the entire time. For example, by using the desired integer equivalent for _amount, and altering other calculations that use _amount to divide by 100.
At the end of the day, I just need to convert 2.05 to 205 and 2.45 to 245 and 1.3 to 130 and so on.
So I decided to “convert” the float value to string before the final transformation. Now it’s working fine.
I’m aware that’s not the pythonic or elegant way to solve the issue, but at least it’s a way to circumvent all the complexities of numerical analyses quickly.
The decimal module provides better ways to convert float to Decimal values than relying on str to produce floating-point literals.
# Demonstrate the problem with 2.05 in the first place
>>> decimal.Decimal.from_float(2.05)
Decimal('2.04999999999999982236431605997495353221893310546875')
# A solution that explicitly spells out the desired outcome.
>>> decimal.Context(prec=3).create_decimal_from_float(2.05)
Decimal('2.05')
I did; it doesn’t rely on an intermediate conversion to a str value. (Or for all I know, it does, and this details are hidden in the implementation of create_decimal_from_float. Point is, I’m not re-inventing the wheel.)
The point is, I am using a method specifically designed to convert a float value to a Decimal value.
The problem with 12.05 is that correct prec argument depends on the magnitude of the value to convert. Perhaps the quantize method is better:
>>> [Decimal(v).quantize(Decimal('0.01')) for v in [1.05, 2.05, 3.05, 4.05, 12.05]]
[Decimal('1.05'), Decimal('2.05'), Decimal('3.05'), Decimal('4.05'), Decimal('12.05')]
But my main goal here is not to solve the problem, but to point out that arbitrary string conversions are not the solution.
I’m not trying to do string conversions at all. OP is trying to round (a multiple of) a float to an integer. Somebody else though converting a float to a string was a good way to do that.
I don’t have to show that it is wrong, because I’m not contesting a valid claim that it’s right in the first place. I’m pointing out that, if one chooses to use Decimal, there are methods already provided for handling float conversions that don’t involve converting it to a string in the first place.
The string conversion is just another way to get to decimal and round the value. Unclear why you have an issue with that and why you think your way is better.