Hello everyone, I was working through the example usage for the test function `assert_array_almost_equal_nulp`, and it brought up a question regarding the function `spacing`. Here's some example code: #### import numpy as np from numpy.testing import assert_array_almost_equal_nulp np.set_printoptions(precision=50) x = np.array([1., 1e-10, 1e-20]) eps = np.finfo(x.dtype).eps y = x*eps + x # y must be larger than x #### [In]: np.abs(x-y) <= np.spacing(y) [Out]: array([ True, False, True], dtype=bool) [In]: np.spacing(y) [Out]: array([ 2.22044604925031308084726333618164062500000000000000e-16, 1.29246970711410574198657608135931695869658142328262e-26, 1.50463276905252801019998276764447446760789191266827e-36]) [In]: np.abs(x-y) [Out]: array([ 2.22044604925031308084726333618164062500000000000000e-16, 2.58493941422821148397315216271863391739316284656525e-26, 1.50463276905252801019998276764447446760789191266827e-36]) #### I guess I'm a little confused about how the spacing values are calculated. My expectation is that the first logical test should give an output array where all of the results are the same. But it is also very likely that I don't have any idea what's going on. Can someone provide some clarification? Thanks Ryan
It looks to me like spacing is calculating the 1ulp precision for each of your numbers, while x*eps is suffering from a tidge of rounding error and giving you 1-or-2 ulp precisions. Notice that the x*eps values are either equal to or twice the values returned by spacing. -n On Fri, Dec 5, 2014 at 12:25 AM, Ryan Nelson <rnelsonchem@gmail.com> wrote:
Hello everyone,
I was working through the example usage for the test function `assert_array_almost_equal_nulp`, and it brought up a question regarding the function `spacing`. Here's some example code:
#### import numpy as np from numpy.testing import assert_array_almost_equal_nulp np.set_printoptions(precision=50)
x = np.array([1., 1e-10, 1e-20]) eps = np.finfo(x.dtype).eps y = x*eps + x # y must be larger than x ####
[In]: np.abs(x-y) <= np.spacing(y) [Out]: array([ True, False, True], dtype=bool)
[In]: np.spacing(y) [Out]: array([ 2.22044604925031308084726333618164062500000000000000e-16, 1.29246970711410574198657608135931695869658142328262e-26, 1.50463276905252801019998276764447446760789191266827e-36])
[In]: np.abs(x-y) [Out]: array([ 2.22044604925031308084726333618164062500000000000000e-16, 2.58493941422821148397315216271863391739316284656525e-26, 1.50463276905252801019998276764447446760789191266827e-36])
####
I guess I'm a little confused about how the spacing values are calculated. My expectation is that the first logical test should give an output array where all of the results are the same. But it is also very likely that I don't have any idea what's going on. Can someone provide some clarification?
Thanks
Ryan
_______________________________________________ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
-- Nathaniel J. Smith Postdoctoral researcher - Informatics - University of Edinburgh http://vorpus.org
On Thu, Dec 4, 2014 at 4:25 PM, Ryan Nelson <rnelsonchem@gmail.com> wrote:
I guess I'm a little confused about how the spacing values are calculated.
np.spacing(x) is basically the same as np.nextafter(x, np.inf) - x, i.e., it returns the minimum positive number that can be added to x to get a number that's different from x.
My expectation is that the first logical test should give an output array where all of the results are the same. But it is also very likely that I don't have any idea what's going on. Can someone provide some clarification?
For 1e-10, np.spacing() is 1.2924697071141057e-26. 1e-10 * eps is 2.2204460492503132e-26, which, when added to 1e-10 rounds to the closest number that can be represented in a 64-bit floating-point representation. That happens to be 2*np.spacing(1e-10), and not 1*np.spacing(1e-10). -- The information transmitted is intended only for the person(s) or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer. Email transmission cannot be guaranteed to be secure or error-free. -- This information is not intended and should not be construed as investment, tax or legal advice or an offer or solicitation to buy or sell any security. Any offer or solicitation for any private investment fund advised by Edgestream Partners, L.P. or any of its affiliates may only be made by delivery of its confidential offering documents to qualified investors.
Alok Singhal <alok <at> edgestreamlp.com> writes:
On Thu, Dec 4, 2014 at 4:25 PM, Ryan Nelson <rnelsonchem <at>
I guess I'm a little confused about how the spacing values are
calculated.
np.spacing(x) is basically the same as np.nextafter(x, np.inf) - x, i.e., it returns the minimum positive number that can be added to x to get a number that's different from x.
My expectation is that the first logical test should give an output array where all of the results are the same. But it is also very likely
gmail.com> wrote: that I
don't have any idea what's going on. Can someone provide some clarification?
For 1e-10, np.spacing() is 1.2924697071141057e-26. 1e-10 * eps is 2.2204460492503132e-26, which, when added to 1e-10 rounds to the closest number that can be represented in a 64-bit floating-point representation. That happens to be 2*np.spacing(1e-10), and not 1*np.spacing(1e-10).
Thanks Nathaniel and Alok. Your explanations were very helpful. I was expecting that all of those logical tests would come out True. It might have been the example in the doc string for `assert_array_almost_equal_nulp` that was throwing me off a little bit. The precision test in that function is `np.abs(x-y) <= ref`, where `ref` is the spacing for the largest values in the two arrays (which is `y` in my case). In the doc string, this function is run comparing x to (x*eps + x), which seems like it shouldn't throw an error given the logical test in the function. For example, if you change the following `x = np.array([1., 1e-9, 1e-20])`, then the assert test function does not throw an error for that example. Anyway, I guess that is the problem with working at the last unit of precision in these numbers... Pesky floating point values...
participants (3)
-
Alok Singhal -
Nathaniel Smith -
Ryan Nelson