Strange behavior with the lisp random function - random

Is there anyone can explain to me the following behavior concerning the random function with the float numbers and how to get rid of this:
CL-USER> (loop for i from 1 to 20 collect (* 0.1 (random 100)))
;; with sbcl ...
(9.2 4.4 9.5 0.5 9.7 5.8 4.3 9.900001 3.7 6.8 2.6000001 9.5 1.6 8.900001 3.3 1.7 5.1 5.5 4.2000003 8.2)
;; with closure ...
(7.7000003 7.2000003 1.7 5.6 7.5 2.2 5.0 7.6 2.0 4.9 2.9 1.6 0.4 6.1 3.3 7.1 8.7 6.5 5.6 9.2)

That is totally expected and appropriate in the context of floating point numbers. It is the same in every other language.
Binary floating point numbers (as defined by IEEE) cannot represent all decimal fractions exactly. For example, the decimal fraction 0.2 in binary is 0.0011001100110011...., so you cannot represent it exactly with a finite amount of bits. Therefore, many floating point numbers necessarily are rounded. If you add them up then, the rounding errors accumulate. Sometimes they cancel each other out, sometimes not. If you multiply them (as you did), they multiply.
If you want to have the exact fractions, Common Lisp offers you to work with rationals. For example, if you calculate (/ 1 5), you get 1/5, which is the printed representation of such a rational number, and this is exact (internally, the calculation works on the numerator and denominator). You can calculate with these exact numbers:
CL-USER> (+ 1/5 2/3)
13/15
CL-USER> (+ 3/5 2/5)
1
In order to print them out as decimal fractions, you can use the format control ~f, for example:
CL-USER> (format t "~,3f" 13/15)
0.867

What's the strange behavior?
Are you worried that, for example, 0.1 * 99 seems to be 9.90001? That's normal for floating point numbers. They're inexact. They sacrifice exactness to get range. You cannot expect to get something without giving something up.

If you want rational numbers, don't use floats...
(loop for i from 1 to 20 collect (/ (random 100) 10))

(loop for i from 1 to 20 collect (read-from-string (format nil "~v$" 1 (/ (random 100) 10))))

Related

Whole fraction numbers in Scheme

Is there an easy way to display whole rational numbers for example:
(average '(1 2 3 4)) ;returns 2 1/2
I would like it to return 5/2. Thank you.
This is DrRacket-specific behavior. It customizes the Racket print handler to print out certain values in "pretty" ways, some of which aren't even plain text. For example, DrRacket will print images as pictures in the REPL, and it will print syntax objects as fully interactive widgets that display source information along with the datum structure.
Racket reserves the print function to be customized, and it doesn't guarantee the output of such a function. If you want consistent output, use write, which will always produce plain text unless explicitly altered by the programmer.
(write (/ 5 2)) ; => 5/2
Note that in the REPL, print will use the same textual representation that write uses for exact, rational numbers.
You can use numerator and denominator to get the pieces you want. Something like:
(let* ((avg (average '(1 2 3 4)))
(num (numerator avg))
(den (denominator avg)))
(printf "~a/~a~n" num den)))

Gambit scheme incorrect calculation for numbers with decimals

i'm using gambit-c intepreter to evaluate scheme arithmetic operations, but it's results are bit off. for example i execute (+ 23 20.01) and it gives me 43.010000000000005, instead of 43.01.
This only occurs if i use numbers with 2 decimal points.
Is there a fix for this?
It has to do with how floating point calculations are done. Please read What Every Programmer Should Know About Floating-Point Arithmetic.
You are in luck! In Scheme you fix this by using exact numbers:
(+ 23 #e20.01) ; ==> 4301/100
You can make it inexact with:
(exact->inexact (+ 23 #e20.01)) ; ==> 43.01

How can I make this clojure code run faster?

I have a version implemented in Lisp(SBCL) which runs under 0.001 seconds with 12 samples. However this version(in clojure) takes more than 1.1 secs.
What should I do for making this code run as fast as original Lisp version?
To make it sure, my numbers are not including times for starting repl and others. And is from time function of both sbcl and clojure.(Yes, my laptop is rather old atom based one)
And this application is/will be used in the repl, not as compiled in single app, so running thousand times before benchmarking seems not meaningful.
Oh, the fbars are like this: [[10.0 10.5 9.8 10.1] [10.1 10.8 10.1 10.7] ... ], which is
Open-High-Low-Close price bars for the stocks.
(defn- build-new-smpl [fmx fmn h l c o]
(let [fmax (max fmx h)
fmin (min fmn l)
fc (/ (+ c fmax fmin) 3.0)
fcd (Math/round (* (- fc o) 1000))
frd (Math/round (* (- (* 2.0 c) fmax fmin) 1000))]
(if (and (> fcd 0) (> frd 0))
[1 fmax fmin]
(if (and (< fcd 0) (< frd 0))
[-1 fmax fmin]
[0 fmax fmin]))))
(defn binary-smpls-using [fbars]
(let [fopen (first (first fbars))]
(loop [fbars fbars, smpls [], fmax fopen, fmin fopen]
(if (> (count fbars) 0)
(let [bar (first fbars)
[_ h l c _] bar
[nsmpl fmx fmn] (build-new-smpl fmax fmin h l c fopen)]
(recur (rest fbars) (conj smpls nsmpl) fmx fmn))
smpls))))
================================================
Thank you. I managed to make the differences for 1000 iteration as 0.5 secs (1.3 secs on SBCL and 1.8 on Clojure). Major factor is I should have created fbars as not lazy but as concrete(?) vector or array, and this solves my problem.
You need to use a proper benchmarking library; the standard Clojure solution is Hugo Duncan's Criterium.
The reason is that code on the JVM starts running in interpreted mode and then eventually gets compiled by the JIT compiler; it's the steady-state behaviour after JIT compilation that you want to benchmark and not behaviour during the profiling stage. This is, however, quite tricky, since the JIT compiler optimizes no-ops away where it can see them, so you need to make sure your code causes side effects that won't be optimized away, but then you still need to run it in a loop to obtain meaningful results etc. -- quick and dirty solutions just don't cut it. (See the Elliptic Group, Inc. Java benchmarking article, also linked to by Criterium's README, for an extended discussion of the issues involved.)
Cycling the two samples you listed in a vector of length 1000 results in a timing of ~327 µs in a Criterium benchmark on my machine:
(require '[criterium.core :as c])
(def v (vec (take 1000 (cycle [[10.0 10.5 9.8 10.1] [10.1 10.8 10.1 10.7]]))))
(c/bench (binary-smpls-using v))
WARNING: Final GC required 4.480116525558204 % of runtime
Evaluation count : 184320 in 60 samples of 3072 calls.
Execution time mean : 327.171892 µs
Execution time std-deviation : 3.129050 µs
Execution time lower quantile : 322.731261 µs ( 2.5%)
Execution time upper quantile : 333.117724 µs (97.5%)
Overhead used : 1.900032 ns
Found 1 outliers in 60 samples (1.6667 %)
low-severe 1 (1.6667 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
A really good benchmark would actually involve an interesting dataset (all different samples, preferably coming from the real world).
When I run this with 1000 samples I get an answer in 46 ms, though here are some common tips on making clojure code faster:
turn on reflection warnings:
(set! warn-on-reflection true)
add type hints until the reflection warnings go away, which isn't a problem here
make it a lazy sequence so you don't have to construct huge sequences in ram, which results in lots of GC overhead. (in some cases this adds overhead though I think it's a decent idea here)
in cases like this see if incanter can do the job for you (though that may be cheating)
time the creation of the result excluding the time it takes the repl to print it.

MIT-Scheme: Different Behavior on Infinite Loop Depending on Numbers

I was working on the solution of the exercise 1.6 of the SICP book when I saw two different behaviors when I run the code depending on the numbers that I used.
If I use natural numbers when I call the sqrt-iter procedure the interpreter just never stop but when I force the decimal division using float-point numbers the interpreter responds: Aborting!: maximum recursion depth exceeded.
Does anyone know the reason for the different behavior?
I made a gist with my answer to help anyone that wants to run the code, just copy & paste: http://bit.ly/Qv1wru. The mit-scheme version is 9.1.1.
Your good-enough? procedure seems wrong, try with this one:
(define (good-enough? guess x)
(< (abs (- (sqr guess) x)) 0.001))

Scheme : precision of decimal numbers

How can I convert 42.0 to 42.00 in Scheme?
For Example (In Scheme):
When I do (/ 20.00 2), I get 10.0. I want 10.00 as the result of above instead of 10.0
Óscar's solution works well, but an even easier solution is to use SRFI-48, which provides additional format directives.
(display (format "~0,2F" (/ 20.00 2)))
The objects represented by 10.0 and 10.00 are the same. There is no such thing as a fixed-precision decimal number in R5RS Scheme. What do you need the fixed precision for? If it is relevant for output, you need to do formatted printing of some sort. Check your Scheme implementation's documentation about a printf or format function. If, on the other hand, you actually need decimal arithmetic, you will need to either use exact ratios and round explicitly according to the rules you want to use, or use integers and treat them as units of size 1/100.
The numbers 10.0 and 10.00 are exactly the same. Maybe you want to format your output to a string with a fixed number of decimals to the right of the dot? try this:
(define (right-pad number len)
(let* ((nstr (number->string number))
(diff (- len (string-length nstr)))
(pads (if (> diff 0) (make-string diff #\0) "")))
(string-append nstr pads)))
Use it like this:
(display (right-pad (/ 20.00 2) 5))
> 10.00
Notice that the len parameter indicates the total amount of chars desired in the resulting string, including the dot. This solution has the advantage of being independent from external libraries.
If you use racket, I think that could help.
https://docs.racket-lang.org/reference/strings.html#%28def._%28%28lib.racket%2Fformat..rkt%29.~7er%29%29
(~r pi #:precision 4)
"3.1416"

Resources