3

I have a procedure that returns a float to three decimal places.

>(gpa ’(A A+ B+ B))
3.665

Is there any way to round this to 3.67 in Scheme?

I'm using SCM version 5e7 with Slib 3b3, the additional Simply Scheme libraries (simply.scm, functions.scm, ttt.scm, match.scm, database.scm) and the answer library I use loaded.

As an aside, I input this into my computer this morning

> (* 1 (- 0.5 0.4 0.1))
-27.755575615628913e-18

no no no no!

How do you deal with such inaccuracy?

usernvk
  • 77
  • 1
  • 8

1 Answers1

6

Try

(define (round-off z n)
  (let ((power (expt 10 n)))
    (/ (round (* power z)) power)))

> (round-off 3.665 2)
3.66
> (round-off 3.6677 2)
3.67

Note 3.665 rounds to 3.66, not 3.67. (Evens round down; odds round up)

As for your second question. Use exact numbers:

> (* 1 (- #e0.5 #e0.4 #e0.1))
0

> #e0.5
1/2
GoZoner
  • 67,920
  • 20
  • 95
  • 145
  • @[GoZoner](http://stackoverflow.com/users/1286639/gozoner) Nice and clean (mine was kludgy), I like that `(/ (round (* 100 z)) 100)` gets rid of the inaccuracy *and* is a function I can reuse (with whatever power I choose!). Changed `round` to `celing` because it fit what I'm doing. +1. Is `#e` [Racket?](http://en.wikipedia.org/wiki/Racket_programming_language) SCM (R5RS) threw an error and insisted I use `(* 1 (- (inexact->exact 0.5) (inexact->exact 0.4) (inexact->exact 0.1)))`. – usernvk Apr 30 '13 at 14:47
  • 1
    I've never used Racket. The `#e` reader syntax might be after R5RS. – GoZoner Apr 30 '13 at 15:07
  • 1
    @[GoZoner](http://stackoverflow.com/users/1286639/gozoner) +1 for no Racket. I loathe it to bits (full disclaimer, I'm new to scheme). – usernvk Apr 30 '13 at 15:43
  • I use R6RS Ikarus. Larceny (R5RS, R6RS, ERRR5RS) is very good too. Ikarus is blindingly fast. – GoZoner Apr 30 '13 at 18:27