Round To 5
August 13, 2019
We begin by creating a random list of speed readings, biasing it so the round-to-5 speed will be 50:
(define speeds
(do ((n 100 (- n 1))
(xs (list) (cons (+ (random 19.0) 40) xs)))
((zero? n) xs)))
The actual average of the speeds we generated is 49.6 mph:
(define (average xs) (/ (apply + xs) (length xs)))
> (average speeds) 49.59251941983793
Now we need a function to round a number to the nearest 5:
(define (round5 x) (inexact->exact (* (floor (/ (+ x 2.5) 5)) 5)))
> (round5 (average speeds)) 50
A simple solution to a simple problem. You can run the program at https://ideone.com/wqc57b.
Here is a slightly more general solution in standard R7RS Scheme (and
a couple of SRFI helpers only for testing). It allows rounding to
non-integer values too, e.g., the nearest multiple of 25, as the demo
illustrates.
(import (scheme base) (scheme write) (only (srfi 1) list-tabulate) (only (srfi 27) random-integer)) (define (rounded-average delta nums) (* delta (round (/ (apply + nums) (length nums) delta)))) ;; only demo/testing below (define (demo/nums nums) (display (rounded-average 5 nums)) (display (rounded-average 0.25 nums)) (display (inexact (/ (apply + nums) (length nums)))) (newline)) (define (demo1) (demo/nums (list-tabulate 20 (lambda (_) (random-integer 100))))) (define (call-times n proc) (let rec ((i 0) (r #f)) (if (>= i n) r (rec (+ i 1) (proc i))))) (define (demo) (call-times 10 (lambda (_) (demo1)))) (demo)Output:
Klong version: 10 iterations
Code: rnd5::{5*_(x+2.5)%5}; test::{[l]; l::[]; {~x>10}{l::l,40+_19*.rn(); x+1}:~1; .p("avg = ",avg::(+/l)%#l); .p("avg5 = ",rnd5(avg))}; {x<10}{test(); .p(""); x+1}:~0; "" Run: [avg = 47.4] [avg5 = 45] [avg = 46.9] [avg5 = 45] [avg = 49.6] [avg5 = 50] [avg = 47.1] [avg5 = 45] [avg = 46.7] [avg5 = 45] [avg = 49.3] [avg5 = 50] [avg = 45.0] [avg5 = 45] [avg = 48.4] [avg5 = 50] [avg = 48.0] [avg5 = 50] [avg = 50.1] [avg5 = 50] ""Here’s a solution in Python.
def round5(l): avg = round(sum(l) / len(l)) offset = [0, -1, -2, 2, 1] avg += offset[avg % 5] return avg l = [51, 68, 45, 41, 44, 68, 80, 52, 45] print(round5(l))Output:
Rust version
fn main() { let x = vec!(12.1,25.2,27.4,32.1,21.5,1.7,5.6,88.,42.0,19.12,); let avg = x.iter().sum::<f64>()/x.len() as f64; let answer = (avg/5.0 + 0.5) as usize * 5; println!("{}", answer); }