[Python-Dev] Caching float(0.0)

Nick Craig-Wood nick at craig-wood.com
Wed Oct 4 13:52:32 CEST 2006


On Wed, Oct 04, 2006 at 12:42:04AM -0400, Tim Peters wrote:
> [skip at pobox.com]
> > If C90 doesn't distinguish -0.0 and +0.0, how can Python?
> 
> With liberal applications of piss & vinegar ;-)
> 
> > Can you give a simple example where the difference between the two is apparent
> > to the Python programmer?
> 
> Perhaps surprsingly, many (well, comparatively many, compared to none
> ....) people have noticed that the platform atan2 cares a lot:
> 
> >>> from math import atan2 as a
> >>> z = 0.0  # postive zero
> >>> m = -z   # minus zero
> >>> a(z, z)   # the result here is actually +0.0
> 0.0
> >>> a(z, m)
> 3.1415926535897931
> >>> a(m, z)    # the result here is actually -0.0
> 0.0

This actually returns -0.0 under linux...

> >>> a(m, m)
> -3.1415926535897931
> 
> It work like that "even on Windows", and these are the results C99's
> 754-happy appendix mandates for atan2 applied to signed zeroes.  I've
> even seen a /complaint/ on c.l.py that atan2 doesn't do the same when
> 
> z = 0.0
> 
> is replaced by
> 
> z = 0
> 
> That is, at least one person thought it was "a bug" that integer
> zeroes didn't deliver the same behaviors.
> 
> Do people actually rely on this?  I know I don't, but given that more
> than just 2 people have remarked on it seeming to like it, I expect
> that changing this would break /some/ code out there.

Probably!


It surely isn't a big problem though is it?

instead of writing

  if (result == 0.0)
      returned cached_float_0;

we just write something like

  if (memcmp((&result, &static_zero, sizeof(double)) == 0))
      returned cached_float_0;

Eg the below prints (gcc/linux)

The memcmp() way
1: 0 == 0.0
2: -0 != 0.0
The == way
3: 0 == 0.0
4: -0 == 0.0

#include <stdio.h>
#include <string.h>

int main(void)
{
    static double zero_value = 0.0;
    double result;

    printf("The memcmp() way\n");
    result = 0.0;
    if (memcmp(&result, &zero_value, sizeof(double)) == 0)
	printf("1: %g == 0.0\n", result);
    else
	printf("1: %g != 0.0\n", result);

    result = -0.0;
    if (memcmp(&result, &zero_value, sizeof(double)) == 0)
	printf("2: %g == 0.0\n", result);
    else
	printf("2: %g != 0.0\n", result);

    printf("The == way\n");
    result = 0.0;
    if (result == 0.0)
	printf("3: %g == 0.0\n", result);
    else
	printf("3: %g != 0.0\n", result);

    result = -0.0;
    if (result == 0.0)
	printf("4: %g == 0.0\n", result);
    else
	printf("4: %g != 0.0\n", result);

    return 0;
}   

-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick


More information about the Python-Dev mailing list