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"
Related
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)))
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))))
I have been reading from the courses CS61A (Spring 2011) from Berkeley Opencourseware and MIT 6.001 from OCW. One uses STk (called as stk-simply) and the other uses mit-scheme as programming language for the lectures.
I just wrote a simple square root procedure using Heron's method. The file was saved as sqrt.scm
;; setting an accuracy or tolerance to deviation between the actual and the expected values
(define tolerance 0.001)
;; gives average of two numbers
(define (average x y)
(/ (+ x y) 2))
;; gives the absolute values of any number
(define (abs x)
(if (< x 0) (- x) x))
;; gives the square of a number
(define (square x) (* x x))
;; tests whether the guess is good enough by checking if the difference between square of the guess
;; and the number is tolerable
(define (good-enuf? guess x)
(< (abs (- (square guess) x)) tolerance))
;; improves the guess by averaging guess the number divided by the guess
(define (improve guess x)
(average (/ x guess) guess))
;; when a tried guess does not pass the good-enuf test then the tries the improved guess
(define (try guess x)
(if (good-enuf? guess x)
guess
(try (improve guess x) x)))
;; gives back square root of number by starting guess with 1 and then improving the guess until good-enuf
(define (sqr-root x)
(try 1 x))
This works fine in STk.
sam#Panzer:~/code/src/scheme$ sudo stk-simply
[sudo] password for sam:
Welcome to the STk interpreter version 4.0.1-ucb1.3.6 [Linux-2.6.16-1.2108_FC4-i686]
Copyright (c) 1993-1999 Erick Gallesio - I3S - CNRS / ESSI <eg#unice.fr>
Modifications by UCB EECS Instructional Support Group
Questions, comments, or bug reports to <inst#EECS.Berkeley.EDU>.
STk> (load "sqrt.scm")
okay
STk> (sqr-root 25)
5.00002317825395
STk>
But not in scheme.
sam#Panzer:~/code/src/scheme$ sudo scheme
[sudo] password for sam:
MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.
Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Image saved on Thursday October 27, 2011 at 7:44:21 PM
Release 9.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/i386 4.118 || Edwin 3.116
1 ]=> (load "sqrt.scm")
;Loading "sqrt.scm"... done
;Value: sqr-root
1 ]=> (sqr-root 25)
;Value: 1853024483819137/370603178776909
1 ]=>
I checked the manuals but I was unable to find the cause. Can anyone let me know why is this? Or is there an error in the code which I am ignoring?. I am a beginner in both scheme & STk.
Try this, now the code should return the same results in both interpreters (ignoring tiny rounding differences):
(define (sqr-root x)
(exact->inexact (try 1 x)))
The answer was the same all along, it's just that MIT Scheme is producing an exact result by default, whereas STk is returning an inexact value. With the above code in place, we convert the result to an inexact number after performing the calculation. Alternatively, we could perform the conversion from the beginning (possibly losing some precision in the process):
(define (sqr-root x)
(try 1 (exact->inexact x)))
This quote explains the observed behavior:
Scheme numbers are either exact or inexact. A number is exact if it was written as an exact constant or was derived from exact numbers using only exact operations. A number is inexact if it was written as an inexact constant, if it was derived using inexact ingredients, or if it was derived using inexact operations. Thus inexactness is a contagious property of a number.
You'd have both answers look the same if in MIT Scheme you had written:
(sqr-root 25.)
since 'inexactness' is 'sticky'
In Scheme, procedures like +, -, *, / works on different types of numbers, but we don't much see any other generic procedures.
For example, length works only on list so that vector-length and string-length are needed.
I guess it comes from the fact that the language doesn't really offer any mechanism for defining generic procedure (except cond of course) like "type classes" in Haskell or a standardized object system.
Is there an idiomatic scheme way to handle generic procedures that I'm not aware of ?
Keeping in mind that all "different types of numbers" are all scheme numbers (i.e. (number? n) equals #t) - this behavior actually makes sense. +, -, *, / and all other arithmetic operators operate on numbers only (even though in other languages they would be classified as different number types int, long, float, etc...) This is due to the fact that you can't explicitly declare number types in scheme.
If you really need a generic solution, besides using external libraries, the easiest way is to roll your own:
(define org-length length)
(define (length x)
(cond
((string? x) (string-length x))
((vector? x) (vector-length x))
; keep going ...
(else (org-length x))))
No, but you can build your own. Welcome to Scheme!
In the past I've used Swindle to provide generic functions. It's bundled with PLT Scheme. It worked well for me, but it's been a few years. There may be other alternatives out there now.
Read SICP, sections 2.4 and 2.5, which cover the implementation of procedures that can operate on generic data types by means of attaching "tags" to data objects. It's also in lecture 4-B of that MIT video series.
You really want to have an object system for that. You may want to have a look at Tiny CLOS, for instance, which is the de-facto standard object system for Chicken Scheme (see the reference manual), but seems to be available for most Scheme implementations.
Finally, I found out a very neat solution in PLT Scheme :
(require (rename-in scheme [length list-length]))
(define length
(λ (x)
((cond [(list? x) list-length]
[(string? x) string-length]
[(vector? x) vector-length]
[else (error "whatever")]) x)))
(length '(a b c))
(length "abc")
(length #(1 2 3))
How to efficiently generate a list of million random elements in scheme? The following code hits maximum recursion depth with 0.1 million itself.
(unfold (lambda(x)(= x 1000000)) (lambda(x)(random 1000)) (lambda(x)(+ x 1)) 0)
It really depends on the system you're using, but here's a common way to do that in plain scheme:
(let loop ([n 1000000] [r '()])
(if (zero? n)
r
(loop (- n 1) (cons (random 1000) r))))
One note about running this code as is: if you just type it into a REPL, it will lead to printing the resulting list, and that will usually involve using much more memory than the list holds. So it's better to do something like
(define l ...same...)
There are many other tools that can be used to varying degrees of convenience. unfold is one of them, and another is for loops as can be found in PLT Scheme:
(for/list ([i (in-range 1000000)]) (random 1000))
I don't know much scheme but couldn't you just use tail-recursion (which is really just looping) instead of unfold (or any other higher-order function)?
Use the do-loop-construct as described here.
Some one correct me if I am wrong but the Fakrudeen's code should end up being optimized away since it is tail recursive. Or it should be with a proper implementation of unfold. It should never reach a maximum recursion depth.
What version of scheme are you using Fakrudeen?
DrScheme does not choke on a mere million random numbers.
Taking Chicken-Scheme as implementation, here is a try with some results.
(use srfi-1)
(use extras)
(time (unfold (lambda(x)(= x 1000000))
(lambda(x)(random 1000))
(lambda(x)(+ x 1)) 0))
(time (let loop ([n 1000000] [r '()])
(if (zero? n)
r
(loop (- n 1) (cons (random 1000) r)))))
(define (range min max body)
(let loop ((current min) (ret '()))
(if (= current max)
ret
(loop (+ current 1) (cons (body current ret) ret)))))
(time (range 0 1000000 (lambda params (random 1000))))
The results are here with csc -O3 t.scm
0.331s CPU time, 0.17s GC time (major), 12/660 GCs (major/minor)
0.107s CPU time, 0.02s GC time (major), 1/290 GCs (major/minor)
0.124s CPU time, 0.022s GC time (major), 1/320 GCs (major/minor)
As you can see, the version of the author is much more slowlier than using plain tail recursive calls. It's hard to say why the unfold call is much more slowlier but I'd guess that it's because it taking a lot more time doing function calls.
The 2 other versions are quite similar. My version is almost the same thing with the exception that I'm creating a high order function that can be reused.
Unlike the plain loop, it could be reused to create a range of function. The position and current list is sent to the function in case they are needed.
The higher order version is probably the best way to do even if it takes a bit more time to execute. It is probably also because of the function calls. It could be optimized by removing parameters and it will get almost as fast as the named let.
The advantage of the higher order version is that the user doesn't have to write the loop itself and can be used with an abstract lambda function.
Edit
Looking at this specific case. Ef we are to create a million of element ranged between 0 and 999, we could possibly create a fixed length vector of a million and with values from 0 to 999 in it. Shuffle the thing back after. Then the whole random process would depend on the shuffle function which should not have to create new memory swapping values might get faster than generating random numbers. That said, the shuffle method somewhat still rely on random.
Edit 2
Unless you really need a list, you could get away with a vector instead.
Here is my second implementation with vector-map
(time (vector-map (lambda (x y) (random 1000)) (make-vector 1000000)))
# 0.07s CPU time, 0/262 GCs (major/minor)
As you can see, it is terribly faster than using a list.
Edit 3 fun
(define-syntax bigint
(er-macro-transformer
(lambda (exp rename compare)
(let ((lst (map (lambda (x) (random 1000)) (make-list (cadr exp)))))
(cons 'list lst)))))
100000
0.004s CPU time, 0/8888 GCs (major/minor)
It's probably not a good idea to use this but I felt it might be interesting. Since it's a macro, it will get executed at compile time. The compile time will be huge, but as you can see, the speed improvement is also huge. Unfortunately using chicken, I couldn't get it to build a list of a million. My guess is that the type it might use to build the list is overflowing and accessing invalid memory.
To answer the question in the comments:
I'm not a Scheme professional. I'm pretty new to it too and as I understand, the named loop or the high order function should be the way to go. The high order function is good because it's reusable. You could define a
(define (make-random-list quantity maxran)
...)
Then thats the other interesting part, since scheme is all about high order functions. You could then replace the implementation of make-random-list with anything you like. If you need some compile time execution, define the macro otherwise use a function. All that really matters is to be able to reuse it. It has to be fast and not use memory.
Common sense tells you that doing less execution it will be faster, tail recursive calls aren't suppose to consume memory. And when you're not sure, you can hide implementation into a function that can be optimized later.
MIT Scheme limits a computation's stack. Given the size of your problem, you are likely running out of stack size. Fortunately, you can provide a command-line option to change the stack size. Try:
$ mit-scheme --stack <number-of-1024-word-blocks>
There are other command-line options, check out mit-scheme --help
Note that MIT Scheme, in my experience, is one of the few schemes that has a limited stack size. This explains why trying your code in others Schemes will often succeed.
As to your question of efficiency. The routine unfold is probably not implemented with a tail-recursive/iterative algorithm. Here is a tail recursive version with a tail recursive version of 'list reverse in-place':
(define (unfold stop value incr n0)
(let collecting ((n n0) (l '()))
(if (stop n)
(reverse! l)
(collecting (incr n) (cons (value n) l)))))
(define (reverse! list)
(let reving ((list list) (rslt '()))
(if (null? list)
rslt
(let ((rest (cdr list)))
(set-cdr! list rslt)
(reving rest list)))))
Note:
$ mit-scheme --version
MIT/GNU Scheme microcode 15.3
Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO warranty; not even
for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Image saved on Tuesday November 8, 2011 at 10:45:46 PM
Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/x86-64 4.118 || Edwin 3.116
Moriturus te saluto.