Consider this example-
(-25.0000001**2)**(1/2)
This returns-
Python 3.8.3
(1.5308085050574255e-15+25.0000001j)
Now I expected some tiny errors. But this looks like a complex number. What does this mean?
Does python simply use the complex representation to describe numbers with very tiny decimals?
Also, I know that this is hugely inefficient but just to test the limits.
That is just a side-effect of Python Operator Precedence, you'll realize that
>>> -25**2
-625
>>> (-25)**2
625
Since the exponentian (**) is given precedence over negative(-) the result comes out to be -625. which square rooted gives you that complex number.
You should be doing this instead:
>>> ((-25.0000001)**2)**(1/2)
25.0000001
Related
I've written a large program, with dependencies on libraries written in my lab. I'm getting wrong (and somewhat random) results, which are caused by floating-point errors.
I would like to do some python magic and change all floats to decimals, or some other more precise type.
I can't write the full code here, but following is the general flow -
def run(n):
...
x = 0.5 # initializes as float
for _ in range(n):
x = calc(x)
...
return x
What I'm trying to avoid is to go over all initialization in the code and add a manual cast to decimal.
Is there a trick I can do to make python initialize all floats in lines such as x = 0.5 as decimals? or perhaps use a custom interpreter which has more exact floats?
Thanks,
I can't post the full code, hope my edit makes it clearer.
I think you can use this:
from decimal import Decimal
Decimal(variable)
So I was trying to get e^(pi*I)=-1, but python 3 gives me another, weird result:
print(cmath.exp(cmath.pi * cmath.sqrt(-1)))
Result:
(-1+1.2246467991473532e-16j)
This should in theory return -1, no?
(Partial answer to the revised question.)
In theory, the result should be -1, but in practice the theory is slightly wrong.
The cmath unit uses floating-point variables to do its calculations--one float value for the real part of a complex number and another float value for the imaginary part. Therefore the unit experiences the limitations of floating point math. For more on those limitations, see the canonical question Is floating point math broken?.
In brief, floating point values are usually mere approximations to real values. The value of cmath.pi is not actually pi, it is just the best approximation that will fit into the floating-point unit of many computers. So you are not really calculating e^(pi*I), just an approximation of it. The returned value has the exact, correct real part, -1, which is somewhat surprising to me. The imaginary part "should be" zero, but the actual result agrees with zero to 15 decimal places, or over 15 significant digits compared to the start value. That is the usual precision for floating point.
If you require exact answers, you should not be working with floating point values. Perhaps you should try an algebraic solution, such as the sympy module.
(The following was my original answer, which applied to the previous version of the question, where the result was an error message.)
The error message shows that you did not type what you thought you typed. Instead of cmath.exp on the outside of the expression, you typed math.exp. The math version of the exponential function expects a float value. You gave it a complex value (cmath.pi * cmath.sqrt(-1)) so Python thought you wanted to convert that complex value to float.
When I type the expression you give at the top of your question, with the cmath properly typed, I get the result
(-1+1.2246467991473532e-16j)
which is very close to the desired value of -1.
Found the answer.
First of all, python 3 cannot properly compute irrational numbers, and so e^(pi*I) will not return -1, as per This answer
Secondly, python 3 returns any complex number as a cartesian pair (real + imaginary).
The fix was to extract the real part of the number:
print(cmath.exp(cmath.pi * cmath.sqrt(-1)).real)
In Python3 (I am using 3.6) they decided to start outputting Integral values.
That created the following problem for me. Suppose that we input a large float
math.floor(4.444444444444445e+85)
The output in this case is being
44444444444444447395279681404626730521364975775215375673863470153230912354225773084672
In Python2.7 the output used to be 4.444444444444445e+85.
Question 1: Is the output in 3.6 reproducible? In other words, what is it? Computing several times in different computers gave me the same result. I guess then that it is a value depending only on the input 4.444444444444445e+85. My guess what it is is that it is the floor of the binary representation of that float. The factorization of the output is
2^232 × 3 × 17 × 31 × 131 × 1217 × 1933 × 13217
where that factor 2^232 is close to the 10^70 that the scientific notation has, but I am not completely sure.
Question 2: I think I know how to take a float 4.444444444444445e+85, extract its significand and exponent, and produce myself that actual integral value of 4444444444444445*10**70 or the float 4.444444444444445e+85, which in my opinion seems a more honest value of for the floor of float(4.444444444444445e+85). Is there a neat way to recover this (allow me to call it) honest floor?
Ok, I retract about calling 'honest' to the floor of the decimal representation. Since the computer stores the numbers in binary, it is fair calling honest the output computed for the binary representation. This, if my guess for Question 1 is correct.
Displaying the output in hex should be helpful:
>>> import math
>>> math.floor(4.444444444444445e+85)
44444444444444447395279681404626730521364975775215375673863470153230912354225773084672
>>> hex(_)
'0x16e0c6d18f4bfb0000000000000000000000000000000000000000000000000000000000'
Note all the trailing zeroes! On almost all platforms, Python floats are represented by the hardware with a significand containing 53 bits, and a power-of-2 exponent. And, indeed,
>>> (0x16e0c6d18f4bfb).bit_length() # the non-zero part does have 53 bits
53
>>> 0x16e0c6d18f4bfb * 2**232 # and 232 zero bits follow it
44444444444444447395279681404626730521364975775215375673863470153230912354225773084672
So the integer you got back is, mathematically, exactly equal to the float you started with. Another way to see that:
>>> (4.444444444444445e85).hex()
'0x1.6e0c6d18f4bfbp+284'
If you want to work with decimal representations instead, see the docs for the decimal module.
Edit: as discussed in comments, perhaps what you really want here is simply
float(math.floor(x))
That will reproduce the same result Python 2 gave for
math.floor(x)
For a long time now I've used this little "algorithim" to snap things to a grid in python 2.7:
mouse_x,mouse_y=31,45
mse=[mouse_x,mouse_y]
mse_snap=(((mse[0])/32)*32,((mse[1])/32)*32)
print(mse_snap)
and it would output: [0,32]
essentially snapping it to the closest position on a 32x32 grid (or whatever size I wanted).
BUT! Now, I've upgraded to Python 3.6 and the exact same code outputs: [31.0,45.0]
I don't really know whats going on here, or where to begin researching to find out. Can anyone offer some intel.
Python 2 integer division also floors the result, while Python 3 will return a floating point number.
Python 2.7:
>>> 31/32
0
Python 3.5:
>>> 31/32
0.96875
You can make it behave as expected by replacing the last line with
mse_snap=(int((mse[0])/32)*32, int((mse[1])/32)*32)
Edit: This is identical as long as the values are positive. Converting to an int rounds towards zero, which is identical to floor only with positive numbers. If you expect negative values, use math.floor instead:
from math import floor
...
mse_snap=(floor((mse[0])/32)*32, floor((mse[1])/32)*32)
I am trying to solve fractional knapsack problem.
I have to find items with maximum calories per weight. I will fill my bag up to defined/limited weight with maximum calories.
Though algorithm is true, I can't find true result because of python division weirdness
When I try to find items with max calories per weight (python3)
print ((calories_list[i]/weight_list[i])*10)
# calories[i] 500 and weight[i] 30 (they're integers)
166.66666666666669
on the other hand, I opened terminal and typed python3
>>> 500/30
16.666666666666668
#when multiply with 10, it must be 16.666666666666668 not
#166.66666666666669
as you see, it gives different results
most of all, the important thing is that the real answer
500/30=16.6666666667
I got stucked here two days ago, please help me
Thanks you
As explained in the Python FAQ:
The float type in CPython uses a C double for storage. A float object’s value is stored in binary floating-point with a fixed precision (typically 53 bits) and Python uses C operations, which in turn rely on the hardware implementation in the processor, to perform floating-point operations. This means that as far as floating-point operations are concerned, Python behaves like many popular languages including C and Java.
You could use the decimal module as an alternative:
>>> from decimal import Decimal
>>> Decimal(500)/Decimal(30)
Decimal('16.66666666666666666666666667')