Reputation: 471
I'm working on the exercises from Chapter 5 of How to Think Like a Computer Scientist, and am trying to solve the 3rd exercise:
Write a function
slope(x1, y1, x2, y2)
that returns the slope of the line through the points (x1, y1) and (x2, y2). Be sure your implementation ofslope
can pass the following doctests:def slope(x1, y1, x2, y2): """ >>> slope(5, 3, 4, 2) 1.0 >>> slope(1, 2, 3, 2) 0.0 >>> slope(1, 2, 3, 3) 0.5 >>> slope(2, 4, 1, 2) 2.0 """
This is the code I've come up with:
def slope(x1, y1, x2, y2):
"""
>>> slope(5, 3, 4, 2)
1.0
>>> slope(1, 2, 3, 2)
0.0
"""
sy = float(y1 - y2)
sx = float(x1 - x2)
return sy / sx
On the 2nd doctest I'm getting -0.0
instead of 0.0
… which is confusing, since I didn't know -0.0
was a thing. I know I can use abs()
to get the absolute value but, then if I do have parameters that should come out to a negative number, it won't work.
Also know I can set a condition on the result so it uses the absolute value or doesn't, but I'm wondering if I'm just doing something wrong here.
Upvotes: 1
Views: 287
Reputation: 59108
You can write a version of slope()
that returns positive 0.0
for the arguments in that doctest by swapping the order of y1 - y2
and x1 - x2
in your code:
def slope(x1, y1, x2, y2):
"""
>>> slope(5, 3, 4, 2)
1.0
>>> slope(1, 2, 3, 2)
0.0
"""
sy = float(y2 - y1)
sx = float(x2 - x1)
return sy / sx
>>> slope(1, 2, 3, 2)
0.0
You'll still get -0.0
if the arguments are reversed:
>>> slope(3, 2, 1, 2)
-0.0
… but outside of doctests that's unlikely to matter, since 0.0
and -0.0
are equal by definition. However, if you want to be sure of always returning a positive zero, you can just add zero to your return value:
def slope(x1, y1, x2, y2):
"""
>>> slope(5, 3, 4, 2)
1.0
>>> slope(1, 2, 3, 2)
0.0
"""
sy = float(y2 - y1)
sx = float(x2 - x1)
return sy / sx + 0 # prevent -0.0
>>> slope(1, 2, 3, 2)
0.0
>>> slope(3, 2, 1, 2)
0.0
The "add positive zero" trick is arbitrary and essentially magical behaviour, and works simply because the IEEE 754 floating point standard says it must:
When the sum of two operands with opposite signs (or the difference of two operands with like signs) is exactly zero, the sign of that sum (or difference) shall be +0 in all rounding-direction attributes except roundTowardNegative; under that attribute, the sign of an exact zero sum (or difference) shall be −0. However, x + x = x − (−x) retains the same sign as x even when x is zero.
— IEEE 754, Section 6.3
More information about signed zero in floating point arithmetic can be found at What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Upvotes: 2