This question already has an answer here:
Inconsistent behavior in np.arange?
(1 answer)
Closed 2 years ago.
I encountered a question when I wanted to generate a numpy array using numpy.arange.
For example, I want to generate an array that contains 3862 elements:
array1=numpy.arange(3.5678,3.5678+3862*0.0001,0.0001)
But the shape of array1 is (3863,). And what made me more confused is this:
In:
numpy.arange(3.5678,3.5678+3860*0.0001,0.0001).shape
numpy.arange(3.5678,3.5678+3861*0.0001,0.0001).shape
numpy.arange(3.5678,3.5678+3862*0.0001,0.0001).shape
numpy.arange(3.5678,3.5678+3863*0.0001,0.0001).shape
Out:
(3861,);(3861,);(3863,);(3863,)
Why did this happen? Due to the precision?
Many thanks!
According to numpy doc:
For floating point arguments, the length of the result is ceil((stop - start)/step). Because of floating point overflow, this rule may result in the last element of out being greater than stop.
And also:
stop number:
End of interval. The interval does not include this value, except in some cases where step is not an integer and floating point round-off affects the length of out.
You can check out this duplicate question or this one for more detail and info on how to deal with the situation.
Related
This question already has an answer here:
What are some possible calculations with numpy or scipy that can return a NaN? [closed]
(1 answer)
Closed 1 year ago.
Not a very important question but I was just curious about the following behavior in Python:
1e500 - 1e500
>>> nan
What is the reasoning for this behavior and why does it not return 0?
I suppose most calculations using 1e500 are pretty weird too but to me at least this 1e500 - 10000 = inf makes sense since the difference would be negligible.
Edit
This question was suggested as holding the answer to my question but in my opinion the answer doesn't explain why this wouldn't be 0, just that it would be NaN.
1e500 is too big to represent in a double precision floating point number, so it turns into inf.
inf-inf gives NaN.
I was thinking of 1e500 as a number, but the real issue is that in Python 1e500 is considered infinity, as it uses whatever floating-point types the underlying platform makes available, which is standard IEEE 754 behavior (Thank you #chpner for that explanation in the comments).
Therefore, the calculation is impossible since infinity - infinity is itself impossible (explained here), which I did not know before.
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
I have a question but I do not know what is the relevant part to search or read about.
I would like to calculate some values but Python gives me a rounded value. For example np.exp(3.832781064493026e-31) = 1 but it should not be 1. What is the way of avoiding these approximations? It should be like 1.00000000000000000000000000000384922.
There is mpmath, numpy's multiprecission cousin:
from mpmath import mp
mp.dps = 100
print(mp.exp(3.832781064493026e-31))
# 1.000000000000000000000000000000383278106449302614152558221812007328689735262269801950763925404522797
print(np.expm1(3.832781064493026e-31))
# 3.832781064493026e-31
print(1+np.expm1(3.832781064493026e-31))
# 1.0
# the second term is eaten away by the 64 bit precission (about 16 decimal digits)
Note that mpmath is quite slower than numpy, doesn't work with numpy's arrays and doesn't mix well with other libraries.
Alternatively, especially if you want to calculate exp(x)-1, there is numpy's expm1. This function is introduced because of the precission problems you run into when first calculating exp(x) and then subtracting 1 for small values of x. A better explanation can be found in this post and more thoroughly here.
This question already has answers here:
How to round to 2 decimals with Python? [duplicate]
(21 answers)
Closed 4 years ago.
How would I format my float digits so that there is always 7 digits no matter the direction?
The value could be any of the following but I always want 7 like below
0.0054233
1234567
123.1224
1.992923
The portion I have right now is
return "%.7f" % fd
How can I adjust that to get my desired output? or maybe link me to something similar I could try and read from..>?
Try if this can work for you:
n = 123.456789
decimals = 7 - len(str(int(n)))
print('{:.{prec}f}'.format(n, prec=decimals))
#=> 123.4568
The drawback is that it rounds up.
It depends on the context of the program, in my opinion... If you just want the numbers to the right to be 6 decimals, use:
"{:.6f}".format(whatevervar)
In other contexts maybe convert it to a string and use len() to evaluate the number of digits.
Hope this helps!
EDIT: Seeing your comments, I would recommend using a conditional to define what you are trying to do. When the number has no decimals (check this thread for how to do it: How to check if a float value is a whole number ) leave it as it is, when it has decimals, round it up with the code I posted above.
This question already has answers here:
Understanding slicing
(38 answers)
Closed 5 years ago.
I am very new to Python and I encountered one issue that I cannot understand. Let say I have string variable:
myVar = "abcdefgh"
I want to display it backward, no problem:
print(myVar[::-1])
and I get hgfedcba. Nothing surprising here. I should get the same with this somewhat verbose code:
print(myVar[len(myVar)-1:0:-1])
but this time the result is hgfedcb. Then I have tried not to subtract 1 from len(myVar) and the result was exactly the same. I do not understand why, especially that lines:
print(myVar[::1])
print(myVar[0:len(myVar):1])
display the same results.
So, my question is why print(myVar[len(myVar):0:-1]) does not display "a"?
The verbose equivalent of print(myVar[::-1]) would be:
print(myVar[-1:-1-len(myVar):-1])
# Or
# print(myVar[len(myVar)-1:-1-len(myVar):-1])
# but this makes the the length invariant less obvious
Note that the stop parameter is exclusive, and in order to get to the actual -1, you have to additionally subtract the full length as negative indexing starts at the end of the sequence. Note also how (stop-start)*step is still the length of the slice.
This question already has answers here:
round() doesn't seem to be rounding properly
(20 answers)
Closed 6 years ago.
The community reviewed whether to reopen this question 5 months ago and left it closed:
Original close reason(s) were not resolved
The Python round() function will theoretically take negative numbers to round to places left of the decimal. [ I.e. round(150, -2) => 200]
However, it seems to be very susceptible to floating point error.
For example, given a large number say 2e25, it gives weird results.
2e25 === 20000000000000000000000000
But, round(2e25, -23) gives a value like
20000000000000000273942742
When it should just be getting 20000000000000000000000000
I know there's a formatting function, a la this thread:
round() in Python doesn't seem to be rounding properly
However, that only seems to work for rounding to the right of the decimal. Am I wrong? Is there another way to do this? Very frustrating trying to get the math right.
Thanks!
The problem is that 2e25 doesn't actually equal 20000000000000000000000000.
>>> 2e25 == 20000000000000000000000000
False
>>> 2e25 == 20000000000000001811939328
True
The float type doesn't have enough precision to represent such a large integer exactly. Unless you have a good reason for using floating-point values, use integers instead.