Python multiplication equivalent to integer division - python

In python using // for division forces the result to be an integer. Is there an equivalent for multiplication?
For example, assume I have an integer W which I scale by a float f. It could be nice to have an operator such as .*, so that:
int(W*f)==W.*f
Would be True.

// does not "force the result to be an integer", this may be coincidentally true, but describing the operator in this presumptuous way is (I believe) resulting in you thinking that there should be other analogous features, which there really aren't. // is "floor division", which any type can overload to have any desired behaviour. There is no "floor multiplication" operator. If you want the result of multiplication to be forced to an integer, you've already shown a perfectly acceptable and straightforward way to do this:
int(W*f)

No, and there is unlikely to be one added, for two reasons.
The current options are short and built-in
There is no ambiguity to be resolved
When you take 12/5 you can reasonably want a integer, quotient, or real, all of which are well defined, take different values in python (without infinite floating precision) and behave differently.
When you multiply 12*5, you could also want those three, but the value will be identical.
For something like pi * 100000, you would need to know the type to end up with as well as the resolution technique for e.g. float to integer (floor, ceiling, round closest, round .5 up, round .5 down, bankers rounding). Without strong types this becomes a mess to hand down from above, and easier to delegate to the user and their own needs or preferences.

Related

How to fix incorrect decimal places of a multiplication result

I'm having a problem with the following calculation:
>>> print(float('32.31') * 1e9)
32310000000.000004
I need this result to be 32310000000.0 (without the false decimal place). This also occurs when using a float directly:
>>> print(32.31 * 1e9)
32310000000.000004
Is there a way to avoid the false decimal place? Analysing the string and rounding to the number of decimal places is not a pefered solution.
Many thanks in advance.
NOTE: The following works fine:
>>> print(32.32 * 1e9)
32320000000.0
so I'm really happy I found the problem above during testing.
EDIT: Thank you for your quick answers! Sorry, I've missed an important point. The method must also work for when the result is less than one, e.g.:
32.31 * 1e-9
...in this case I cannot use round(32.31 * 1e-9, 1)
One way to avoid your problem is to use the decimal module, which works in base ten and thus works the way humans would work (if we were much faster).
from decimal import Decimal
value = float(Decimal('32.31') * Decimal(1e9))
This yields the value you want,
32310000000.0
Another way is to use the fractions module, which works with exact values:
from fractions import Fraction
value = float(Fraction('32.31') * Fraction(1e9))
Note that in both of these methods, we must convert 1e9 and not just the decimal value. Using 1e9 as a float converts the intermediate values to float and the approximation problem pops up again. In either method, you could leave off the final conversion to float type and just continue to work with a Decimal or Fraction value. Either of these methods is somewhat slower than using float types: you gain accuracy at the expense of speed. That speed decrease may matter in some situations.
Regarding your edit to your question: using the value 1e-9 in either of my methods will still result in what you want, namely the value 3.231e-08.
If you are just interested in printing with a single decimal place, you can use round by specifying the number after decimal you want to have, in this case 1
print(round(float('32.31') * 1e9, 1))
# 32310000000.0
This is caused by the representation limitation of the floats's binary mantissa. 32.31 cannot be represented by a division by a power of two. If you know your values will always be integers (or a known number of decimal places), you can use round() or int(round()) to circumvent the limitation.
I'm going to assume you're using Python 3.
If you only care about the result being printed, use string formatting:
print("{r:1.2f}".format(r=32.31 * 1e9))
Another way to do it is using the older formatting syntax:
print("%1.1f" % (32 * 1e9))
I prefer the first, but either will work.

When does Python perform type conversion when comparing int and float?

Why does Python return True when I compare int and float objects which have the same value?
For example:
>>> 5*2 == 5.0*2.0
True
It's not as simple as a type conversion.
10 == 10.0 delegates to the arguments' __eq__ methods, trying (10).__eq__(10.0) first, and then (10.0).__eq__(10) if the first call returns NotImplemented. It makes no attempt to convert types. (Technically, the method lookup uses a special routine that bypasses instance __dict__ entries and __getattribute__/__getattr__ overrides, so it's not quite equivalent to calling the methods yourself.)
int.__eq__ has no idea how to handle a float:
>>> (10).__eq__(10.0)
NotImplemented
but float.__eq__ knows how to handle ints:
>>> (10.0).__eq__(10)
True
float.__eq__ isn't just performing a cast internally, either. It has over 100 lines of code to handle float/int comparison without the rounding error an unchecked cast could introduce. (Some of that could be simplified if the C-level comparison routine didn't also have to handle >, >=, <, and <=.)
Objects of different types, except different numeric types, never compare equal.
And:
Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the “narrower” type is widened to that of the other, where integer is narrower than floating point, which is narrower than complex. Comparisons between numbers of mixed type use the same rule.
https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex
The comparison logic is implemented by each type's __eq__ method. And the standard numeric types are implemented in a way that they support comparisons (and arithmetic operations) among each other. Python as a language never does implicit type conversion (like Javascript's == operator would do implicit type juggling).
The simple answer is that the langue is designed this way. Here is an excerpt from the documentation supporting this:
6.10.1 Value Comparisons
Numbers of built-in numeric types (Numeric Types — int, float, complex) and of the standard library types fractions.Fraction and decimal.Decimal can be compared within and across their types, with the restriction that complex numbers do not support order comparison.
In other words, we want different numeric types with the same value to be equal.
PEP 20
Special cases aren't special enough to break the rules.
Although practicality beats purity.
What benefit is there to making numeric types not comparable, besides making life difficult in most common cases?
You can have a look at the source code for the CPython implementation.
The function is preceded by this comment explaining how the conversion is attempted:
/* Comparison is pretty much a nightmare. When comparing float to float,
* we do it as straightforwardly (and long-windedly) as conceivable, so
* that, e.g., Python x == y delivers the same result as the platform
* C x == y when x and/or y is a NaN.
* When mixing float with an integer type, there's no good *uniform* approach.
* Converting the double to an integer obviously doesn't work, since we
* may lose info from fractional bits. Converting the integer to a double
* also has two failure modes: (1) an int may trigger overflow (too
* large to fit in the dynamic range of a C double); (2) even a C long may have
* more bits than fit in a C double (e.g., on a 64-bit box long may have
* 63 bits of precision, but a C double probably has only 53), and then
* we can falsely claim equality when low-order integer bits are lost by
* coercion to double. So this part is painful too.
*/
Other implementations are not guaranteed to follow the same logic.
From the documentation:
Python fully supports mixed arithmetic: when a binary arithmetic
operator has operands of different numeric types, the operand with the
“narrower” type is widened to that of the other, where plain integer
is narrower than long integer is narrower than floating point is
narrower than complex. Comparisons between numbers of mixed type use
the same rule.
According to this 5*2 is widened to 10.0 and which is equal to 10.0
If you are comparing the mixed data types then the result will be considered on the basics of data type which is having long range, so in your case float range is more then int
float max number can be --> 1.7976931348623157e+308
int max number can be --> 9223372036854775807
Thanks
The == operator compares only the values but not the types. You can use the 'is' keyword to achieve the same effect as using === in other languages. For instance
5 is 5.0
returns
False
==
is a comparison operator
You are actually asking the interpreter if both sides of your expression are equal or not.
In other words you are asking for it to return a Boolean value, not to convert data types. If you want to convert the data types you will have to do so implicitly in your code.

Division in python an types

I have a code which part of it looks like this,
A=(-1//2+(int(math.sqrt(1+8*t)))//2)
if type(A)==int:
print(t)
print(A)
The problem arises when I use "/" to get "A",
Since I am using "/", I always get an extra decimal point. For example 5/5=1.0 or 4/2=2.0 etc, which python interprets it as a float (I am using 3.6.5). Hence whatever the result is my code stuck at line2.
When I use // the same thing happens. I get 5/2=2 which its float actually but it appears as an integer.
Since my code depends on the type of this division how I can solve this problem?
A=(-1//2+(int(math.sqrt(1+8*t)))//2) its a actually the formula for finding the roots of the quadratic equation (where in the equation a=1 and b=1 and c=-2t for ax^2+bx+c) I need only the integer roots with positive values
What you're trying to do won't work. For two integers x and y, x/y is always a float, even if it happens to be integral, and x//y is always an int, even if it has to truncate (throw away) a fractional part. So testing type(A) == int doesn't test for anything except which of the two you used.
There is a method float.is_integer that you can use, and that works fine for integers divided by 2—but it doesn't work once you're using sqrt. Explaining floating-point rounding issues is a big enough job that it takes up a whole paper that's so important that it's been included by reference in multiple language specifications, but the short version is that sqrt could very easily give you a number that's a tiny big bigger or smaller than an integer, so is_integer will give you the wrong answer.
What you probably want to do is something like this:
if math.isclose(A, round(A)):
The round function will round a float to the nearest integer. The isclose function will then check whether the resulting integer is "close enough" to the original float. You should read the docs on isclose to understand exactly what it does, but in this case, I think the default values will be fine, unless you're dealing with huge integers.

Python rounding and inserting into array does not round [duplicate]

So I have a list of tuples of two floats each. Each tuple represents a range. I am going through another list of floats which represent values to be fit into the ranges. All of these floats are < 1 but positive, so precision matter. One of my tests to determine if a value fits into a range is failing when it should pass. If I print the value and the range that is causing problems I can tell this much:
curValue = 0.00145000000671
range = (0.0014500000067055225, 0.0020968749796738849)
The conditional that is failing is:
if curValue > range[0] and ... blah :
# do some stuff
From the values given by curValue and range, the test should clearly pass (don't worry about what is in the conditional). Now, if I print explicitly what the value of range[0] is I get:
range[0] = 0.00145000000671
Which would explain why the test is failing. So my question then, is why is the float changing when it is accessed. It has decimal values available up to a certain precision when part of a tuple, and a different precision when accessed. Why would this be? What can I do to ensure my data maintains a consistent amount of precision across my calculations?
The float doesn't change. The built-in numberic types are all immutable. The cause for what you're observing is that:
print range[0] uses str on the float, which (up until very recent versions of Python) printed less digits of a float.
Printing a tuple (be it with repr or str) uses repr on the individual items, which gives a much more accurate representation (again, this isn't true anymore in recent releases which use a better algorithm for both).
As for why the condition doesn't work out the way you expect, it's propably the usual culprit, the limited precision of floats. Try print repr(curVal), repr(range[0]) to see if what Python decided was the closest representation of your float literal possible.
In modern day PC's floats aren't that precise. So even if you enter pi as a constant to 100 decimals, it's only getting a few of them accurate. The same is happening to you. This is because in 32-bit floats you only get 24 bits of mantissa, which limits your precision (and in unexpected ways because it's in base2).
Please note, 0.00145000000671 isn't the exact value as stored by Python. Python only diplays a few decimals of the complete stored float if you use print. If you want to see exactly how python stores the float use repr.
If you want better precision use the decimal module.
It isn't changing per se. Python is doing its best to store the data as a float, but that number is too precise for float, so Python modifies it before it is even accessed (in the very process of storing it). Funny how something so small is such a big pain.
You need to use a arbitrary fixed point module like Simple Python Fixed Point or the decimal module.
Not sure it would work in this case, because I don't know if Python's limiting in the output or in the storage itself, but you could try doing:
if curValue - range[0] > 0 and...

Byte precision of value in Python?

I have a hash function in Python.
It returns a value.
How do I see the byte-size of this return value? I want to know if it is 4-bytes or 8 or what.
Reason:
I want to make sure that the min value is 0 and the max value is 2**32, otherwise my calculations are incorrect.
I want to make sure that packing it to a I struct (unsigned int) is correct.
More specifically, I am calling murmur.string_hash(`x`).
I want to know sanity-check that I am getting a 4-byte unsigned return value. If I have a value of a different size, them my calculations get messed up. So I want to sanity check it.
If it's an arbitrary function that returns a number, there are only 4 standard types of numbers in Python: small integers (C long, at least 32 bits), long integers ("unlimited" precision), floats (C double), and complex numbers.
If you are referring to the builtin hash, it returns a standard integer (C long):
>>> hash(2**31)
-2147483648
If you want different hashes, check out hashlib.
Generally, thinking of a return value as a particular byte precision in Python is not the best way to go, especially with integers. For most intents and purposes, Python "short" integers are seamlessly integrated with "long" (unlimited) integers. Variables are promoted from the smaller to the larger type as necessary to hold the required value. Functions are not required to return any particular type (the same function could return different data types depending on the input, for example).
When a function is provided by a third-party package (as this one is), you can either just trust the documentation (which for Murmur indicates 4-byte ints as far as I can tell) or test the return value yourself before using it (whether by if, assert, or try, depending on your preference).

Categories

Resources