Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one write the Pythagoras Theorem in Scala?

Tags:

The square of the hypotenuse of a right triangle is equal to the sum of the squares on the other two sides.

This is Pythagoras's Theorem. A function to calculate the hypotenuse based on the length "a" and "b" of it's sides would return sqrt(a * a + b * b).

The question is, how would you define such a function in Scala in such a way that it could be used with any type implementing the appropriate methods?

For context, imagine a whole library of math theorems you want to use with Int, Double, Int-Rational, Double-Rational, BigInt or BigInt-Rational types depending on what you are doing, and the speed, precision, accuracy and range requirements.

like image 897
Daniel C. Sobral Avatar asked Jan 27 '09 23:01

Daniel C. Sobral


People also ask

How do you write Pythagoras Theorem?

The formula of Pythagoras theorem is expressed as, Hypotenuse2 = Base2 + Height2. This is also written as, c2 = a2 + b2; where 'c' is the hypotenuse and 'a' and 'b' are the two legs of the right-angled triangle.

How do you do Pythagoras with only C?

Solving for the hypotenuse, we simply take the square root of both sides of the equation a² + b² = c² and solve for c . When doing so, we get c = √(a² + b²) . This is just an extension of the Pythagorean theorem and often is not associated with the name hypotenuse formula.

What is Pythagoras theorem words?

: a theorem in geometry: the square of the length of the hypotenuse of a right triangle equals the sum of the squares of the lengths of the other two sides.

Is the Pythagorean Theorem Greek?

The Pythagorean Theorem was one of the earliest theorems known to ancient civilizations. This famous theorem is named for the Greek mathematician and philosopher, Pythagoras. Pythagoras founded the Pythagorean School of Mathematics in Cortona, a Greek seaport in Southern Italy.


2 Answers

This only works on Scala 2.8, but it does work:

scala> def pythagoras[T](a: T, b: T, sqrt: T => T)(implicit n: Numeric[T]) = {      | import n.mkNumericOps      | sqrt(a*a + b*b)      | } pythagoras: [T](a: T,b: T,sqrt: (T) => T)(implicit n: Numeric[T])T  scala> def intSqrt(n: Int) = Math.sqrt(n).toInt intSqrt: (n: Int)Int  scala> pythagoras(3,4, intSqrt) res0: Int = 5 

More generally speaking, the trait Numeric is effectively a reference on how to solve this type of problem. See also Ordering.

like image 186
Daniel C. Sobral Avatar answered Nov 03 '22 00:11

Daniel C. Sobral


The most obvious way:

type Num = {   def +(a: Num): Num   def *(a: Num): Num }  def pyth[A <: Num](a: A, b: A)(sqrt: A=>A) = sqrt(a * a + b * b)  // usage pyth(3, 4)(Math.sqrt) 

This is horrible for many reasons. First, we have the problem of the recursive type, Num. This is only allowed if you compile this code with the -Xrecursive option set to some integer value (5 is probably more than sufficient for numbers). Second, the type Num is structural, which means that any usage of the members it defines will be compiled into corresponding reflective invocations. Putting it mildly, this version of pyth is obscenely inefficient, running on the order of several hundred thousand times slower than a conventional implementation. There's no way around the structural type though if you want to define pyth for any type which defines +, * and for which there exists a sqrt function.

Finally, we come to the most fundamental issue: it's over-complicated. Why bother implementing the function in this way? Practically speaking, the only types it will ever need to apply to are real Scala numbers. Thus, it's easiest just to do the following:

def pyth(a: Double, b: Double) = Math.sqrt(a * a + b * b) 

All problems solved! This function is usable on values of type Double, Int, Float, even odd ones like Short thanks to the marvels of implicit conversion. While it is true that this function is technically less flexible than our structurally-typed version, it is vastly more efficient and eminently more readable. We may have lost the ability to calculate the Pythagrean theorem for unforeseen types defining + and *, but I don't think you're going to miss that ability.

like image 28
Daniel Spiewak Avatar answered Nov 02 '22 23:11

Daniel Spiewak