floating away from the rational

37 views
Skip to first unread message

ravas

unread,
May 17, 2015, 4:07:48 PM5/17/15
to sy...@googlegroups.com
My goal is to input the coordinates of the vertices of a triangle and have significant properties printed for a human to read.
I'm aware of the limitation of floating point arithmetic, and I was able to produce an accurate area with the decimal module.

return (sp*(sp-a)*(sp-b)*(sp-c)).sqrt().quantize(dec('1.0000000000'))

However, a version using sympy is also desirable. Do I need to install mpmath / gmpy to compensate for the floating point errors?
Here is the test code:

import sympy.functions as sym
import sympy.geometry as geo

sqrt
= sym.sqrt

def distance(A, B):
 
"""
 A & B are objects with x and y attributes
 :return: the distance between A and B
 """

 dx
= B.x - A.x
 dy
= B.y - A.y
 
return sqrt(dx**2 + dy**2)

def sides(A, B, C):
 
"""
 A, B & C are objects with x and y attributes
 :return: sorted side lengths (smallest to largest)
 """

 a
= distance(B, C)
 b
= distance(A, C)
 c
= distance(A, B)
 
return sorted((a, b, c,), key=float)

def area(a, b, c):
 
"""
 a, b & c are the side lengths of the trigon
 :return: area of the trigon
 """

 p
= a + b + c # perimeter
 sp
= p / 2 # semi-perimeter
 
return sqrt(sp*(sp-a)*(sp-b)*(sp-c))

if __name__ == '__main__':
 p
= geo.Point
 A
= p(0, 0)
 B
= p(3, 0)
 C
= p(3, 3)
 sides
= sides(A,B,C)
 
print(sides)
 
print(area(*sides))

Output: 

[3, 3, 3*sqrt(2)]
sqrt
(-3*sqrt(2)/2 + 3)*sqrt(27*sqrt(2)/4 + 27/2)

Obviously I want 9/2 as the result for the area... but it is giving me a representation of 4.4999999999...
What can I do about this?

Chris Smith

unread,
May 18, 2015, 6:38:51 AM5/18/15
to sy...@googlegroups.com
You could use the attributes of a Triangle object directly (of which there are many, including area):

>>> p=Point
>>> A = p(0, 0)
>>> B = p(3, 0)
>>> C = p(3, 3)
>>> Triangle(A,B,C).area
9/2

or simplify your "manual" result:

>>> simplify(sqrt(-3*sqrt(2)/2 + 3)*sqrt(27*sqrt(2)/4 + S(27)/2))
9/2

/c

ravas

unread,
May 18, 2015, 1:09:07 PM5/18/15
to sy...@googlegroups.com
Thank you!

ravas

unread,
May 20, 2015, 3:11:02 AM5/20/15
to sy...@googlegroups.com
The following produces 9/2 without needing to use simplify. :D

def area(A, B, C):
    """

    A, B & C are objects with x and y attributes
    :return: area of the trigon
    """

    x1
= B.x - A.x
    y1
= B.y - A.y
    x2
= C.x - A.x
    y2
= C.y - A.y
   
return (x1*y2 - x2*y1) / 2

Reply all
Reply to author
Forward
0 new messages