Skip to main content

Recitation 2 — Functions & Conditionals

Skills: 1

Reading: 3.2, 3.3, 3.4

Calculating Distance -- Test First

  • Have each student or group select two landmarks (using Google Maps) that are approximately 1 mile apart according to "measure distance" function (right/ctrl click to use it). They should record the latitude and longitude for each point.
  • Students define their chosen points. For example:
    POINT-A-LAT = 42.3505
    POINT-A-LON = -71.1054

    POINT-B-LAT = 42.3430
    POINT-B-LON = -71.1020
    (Students should use the coordinates they find.)

Write a Helper Function: deg-to-rad**

  • The FCC approximation formula we will use to calculate distance use trigonometric functions, and Pyret's require angles to be in radians, whereas latitude & longitude are in degrees.
  • Have students write a function to convert from degrees to radians. Remember, 2 PI is the same as 360 degrees. The constant PI is built in to Pyret.

Developing FCC Constants


Building the Distance Function

  • Given the following function header:
    fun dist(lat1 :: Number, lat2 :: Number, lon1 :: Number, lon2 :: Number):
    doc: "Calculates the distance between two coordinates using FCC approximation"
    define a function to calculate the distance. The key is that north-south distance is the difference of latitudes multiplied by KPDLAT and the east-west distance is the difference in longitudes multiplied by KPDLON, and then the pythagorean theorem can get the actual distance.

Writing a Test Case

  • At the beginning, we found two points that we chose to be 1 mile apart -- let's write a test using those points:
    fun dist(lat1, lat2, lon1, lon2):
    doc: "Calculates the distance between two coordinates using FCC approximation"
    ...
    where:
    dist(POINT-A-LAT, POINT-B-LAT, POINT-A-LON, POINT-B-LON) is%(within(0.1)) 1
    end
  • Numeric calculations using decimal numbers will often have small inaccuracies, so tests will work better if they test that the output is not equal, but rather, within a certain bound of the expected value. Pyret's is can be followed by %() and then a testing predicate can be placed within the parentheses: the most common one is within(N) where N is some number. This checks that the output is 1 +- 0.1, i.e., that it is greater than 0.9 and less than 1.1.
  • Run the test -- what do you see?

Discovering the Bug

  • If our FCC formulas produce a result based on our constants, why might the computed value be different from 1?
  • If tests fail, either the code is wrong or the tests are wrong. Which is the case here?
  • What is the value that is produced? (Approximately 1.609). What is the relationship between 1.609 and 1?
  • Once you figure out the bug, go back and fix the issue in the code! Re-run to confirm that the bug has been fixed.

Wrap-Up

  • Breaking the problem into parts (helper function, constants, raw computation) helped manage complexity.
  • Test cases (e.g., using real-world data -- two points chosen to be 1 mile apart) revealed the a bug (unit mismatch).
  • In 1999, a space probe was lost because of failure to correctly convert between units! https://en.wikipedia.org/wiki/Mars_Climate_Orbiter