




Scheme Programming Language









Newbie question: what's this dot?
Howdy Schemers, Please direct me to an "FM" (manual) or document to explain this; I've looked in all the ones I have and can't seem to reckon the answer. I'm using MIT Scheme on Slackware 11.0, and also have access to GNU Guile. when I divide using (/ 1 2) or (quotient 1 2) I get 1/2. When I divide using (/ 1 2.) I get 0.5 As I want to use this to calculate Taylor series and other such sequences, I really need the decimal representation. How do I coerce this (do I need to coerce it or is this much simpler)? For example, if I (define series (lambda (x) (/ 1 x))) and then do (map series '(1 2 3 4 5)) I get a list of ones as a result. That's not right ;) It seems as though there's a simple concept here that I'm unaware of. Tell me what it is, please! Thanks, Joel  Joel J. Adamson Biostatistician Pediatric Psychopharmacology Research Unit Massachusetts General Hospital Boston, MA 02114 (617) 6431432 (303) 8803109
On Thu, 31 May 2007, Joel J. Adamson wrote: > Howdy Schemers, > Please direct me to an "FM" (manual) or document to explain this; I've > looked in all the ones I have and can't seem to reckon the answer. > I'm using MIT Scheme on Slackware 11.0, and also have access to GNU > Guile. > when I divide using > (/ 1 2) > or > (quotient 1 2) > I get 1/2. > When I divide using > (/ 1 2.) > I get 0.5 > As I want to use this to calculate Taylor series and other such > sequences, I really need the decimal representation.
Why? > How do I coerce > this (do I need to coerce it or is this much simpler)? > For example, if I > (define series > (lambda (x) > (/ 1 x))) > and then do > (map series '(1 2 3 4 5)) > I get a list of ones as a result. That's not right ;)
Really? Then your scheme is broken. This is what you are supposed to get: (1 1/2 1/3 1/4 1/5) > It seems as > though there's a simple concept here that I'm unaware of. Tell me > what it is, please!
I'm not sure, but I have a feeling that you don't know the concept of rationals in lisp? Anyhow, use the exact>inexact function: (define (series x) (exact>inexact (/ 1 x))) For example, (/ 1 2) is 1/2, and (exact>inexact 1/2) is 0.5.
"Kjetil S. Matheussen" <k.s.matheus@notam02.no> writes:
> On Thu, 31 May 2007, Joel J. Adamson wrote: > > when I divide using > > (/ 1 2) > > or > > (quotient 1 2) > > I get 1/2. > > When I divide using > > (/ 1 2.) > > I get 0.5 > > As I want to use this to calculate Taylor series and other such > > sequences, I really need the decimal representation. > Why?
Because the point of the program is to print out the partial sums of a series, and also find the limit of a series, or tell me that it's divergent. This is just for learning.
> > How do I coerce > > this (do I need to coerce it or is this much simpler)? > > For example, if I > > (define series > > (lambda (x) > > (/ 1 x))) > > and then do > > (map series '(1 2 3 4 5)) > > I get a list of ones as a result. That's not right ;) > Really?
Really. > Then your scheme is broken. This is what you are supposed to get: > (1 1/2 1/3 1/4 1/5)
Hmmm, it's definitely treating them as integers and giving me the integer ceiling. I'm pretty sure it's doing what it's supposed to do, and I'm not doing what I'm supposed to do. I hope you consider that a productive attitude. > I'm not sure, but I have a feeling that you don't know the concept of > rationals in lisp?
Bingo. I will read about it. (btw, I know the concept of rational in mathematics, and so perhaps thinking of it as a subset of real numbers is what's tripping me up; these things seem to have a different meaning; i.e., to scheme, a rational and an integer are different, to me they are the same in the sense that an alligator is a crocodile, i.e., subsets). Thanks for your help, Joel  Joel J. Adamson Biostatistician Pediatric Psychopharmacology Research Unit Massachusetts General Hospital Boston, MA 02114 (617) 6431432 (303) 8803109
On Thu, 31 May 2007, Joel J. Adamson wrote: > "Kjetil S. Matheussen" <k.s.matheus @notam02.no> writes: >> On Thu, 31 May 2007, Joel J. Adamson wrote: >>> when I divide using >>> (/ 1 2) >>> or >>> (quotient 1 2) >>> I get 1/2.
That is also strange. The correct answer for (quotient 1 2) is 0. (Its doing an integer division of 1/2) >>> When I divide using >>> (/ 1 2.) >>> I get 0.5 >>> As I want to use this to calculate Taylor series and other such >>> sequences, I really need the decimal representation. >> Why? > Because the point of the program is to print out the partial sums of a > series, and also find the limit of a series, or tell me that it's > divergent. This is just for learning.
Okay, I thought it might have been to optimize. But if not, then you don't need decimal representation to get a partial sum. At least not with a proper working scheme...
>>> How do I coerce >>> this (do I need to coerce it or is this much simpler)? >>> For example, if I >>> (define series >>> (lambda (x) >>> (/ 1 x))) >>> and then do >>> (map series '(1 2 3 4 5)) >>> I get a list of ones as a result. That's not right ;) >> Really? > Really. >> Then your scheme is broken. This is what you are supposed to get: >> (1 1/2 1/3 1/4 1/5) > Hmmm, it's definitely treating them as integers and giving me the > integer ceiling. I'm pretty sure it's doing what it's supposed to do, > and I'm not doing what I'm supposed to do. I hope you consider that a > productive attitude.
Is both mitscheme and guile working like this? I guess one of them could have a bug or something, but if both of them behaves like this... (Guile didn't get rationals until 1.6 I think though.) >> I'm not sure, but I have a feeling that you don't know the concept of >> rationals in lisp? > Bingo. I will read about it.
Yes. Its very simple. (/ 1 2) is 1/2, which is usually represented internally in scheme by the two integers 1 and 2.
"Kjetil S. Matheussen" <k.s.matheus@notam02.no> writes: > >>> (quotient 1 2) > >>> I get 1/2. > That is also strange. The correct answer for (quotient 1 2) is 0. (Its > doing an integer division of 1/2)
Here's my scheme buffer:  This is the Scheme process buffer. Type Cx Ce to evaluate the expression before point. Type Cc Cc to abort evaluation. Type Mx describemode for more information. Scheme Microcode Version 14.9 MIT Scheme running under GNU/Linux Scheme saved on Monday June 17, 2002 at 10:03:44 PM Release 7.7.1 Microcode 14.9 Runtime 15.1 (quotient 1 2) ;Value: 0 (quotient 1 2.) ;Value: 0. (/ 1 2) ;Value: 1/2 (/ 1 2.) ;Value: .5 (exact>inexact (/ 1 2)) ;Value: .5 (+ (/ 1 2) (/ 1 3)) ;Value: 5/6  > > Because the point of the program is to print out the partial sums of a > > series, and also find the limit of a series, or tell me that it's > > divergent. This is just for learning. > Okay, I thought it might have been to optimize. But if not, then you > don't need decimal representation to get a partial sum. At least not > with a proper working scheme...
I don't *need* the decimal representation, it's just cosmetically superior: I would rather have a list of 0.34762, 0.3476178, ... than a list like 1/344, 1/345,...print out from my function. thanks again for helping out, Joel  Joel J. Adamson Biostatistician Pediatric Psychopharmacology Research Unit Massachusetts General Hospital Boston, MA 02114 (617) 6431432 (303) 8803109
Joel J. Adamson skrev: > "Kjetil S. Matheussen" <k.s.matheus @notam02.no> writes: >>>>> (quotient 1 2) >>>>> I get 1/2. >> That is also strange. The correct answer for (quotient 1 2) is 0. (Its >> doing an integer division of 1/2)
> 1/2. [bug icon] reference to undefined identifier: 1/2. Ah! You didn't get "1/2.". You got "1/2". :) If an number is exact the printer will use fraction notation. To convert an exact number to an inexact use exact>inexact. > (exact>inexact 1/2) 0.5 Since floating point numbers such as "2." (short for 2.0) are inexact, the result of (/ 1 2.) is inexact. It is therefore printed as 0.5. /Jens Axel Sgaard
Jens Axel Sgaard <use@soegaard.net> writes: > Ah! > You didn't get "1/2.".
That's right: quotient does produce 0 as expected. Right: my question about the dot is really how to use it get the behavior I want when binding a parameter. As you have now filled me in, what I want is for these to be done as floating point operations, instead of fixnum operations. > If an number is exact the printer will use fraction notation. > To convert an exact number to an inexact use exact>inexact. > > (exact>inexact 1/2) > 0.5
Is this the best way? Or should I be specifying the operations as floating point arithmetic, e.g., (flo:/ or some such beast...? Thanks  this is a very helpful group, Joel  Joel J. Adamson Biostatistician Pediatric Psychopharmacology Research Unit Massachusetts General Hospital Boston, MA 02114 (617) 6431432 (303) 8803109
Joel J. Adamson skrev:
> Jens Axel Sgaard <use @soegaard.net> writes: >> Ah! >> You didn't get "1/2.". > That's right: quotient does produce 0 as expected. >> You got "1/2". :) > Right: my question about the dot is really how to use it get the > behavior I want when binding a parameter. As you have now filled me > in, what I want is for these to be done as floating point operations, > instead of fixnum operations. >> If an number is exact the printer will use fraction notation. >> To convert an exact number to an inexact use exact>inexact. >> > (exact>inexact 1/2) >> 0.5 > Is this the best way? Or should I be specifying the operations as > floating point arithmetic, e.g., (flo:/ or some such beast...?
All the standard operations work on both exact and inexact numbers. Consider sqrt. The square root of an inexact number is inexact. > (sqrt 4.0) 2.0 If an exact number has a rational square root the result is exact (on some implementations): > (sqrt 1/9) 1/3 The square root 1/7 is an irrational number (since 7 is prime), so here a floating point number is used to represent the result: > (sqrt 1/7) 0.3779644730092272 I normally use exact numbers in the computation. If I want the result printed as a floating point number, I convert it with inexact>exact. Well, if you promise not to tell anyone: In the repl I usually use just multiply with 1. .  Jens Axel Sgaard  Jens Axel Sgaard
Hi Joel, I've seen the posts so far and it appears the answer has been done to death. Like you, I was taken by surprise when something like this (/ 1 2) ; returned 1/2. I "knew" it was correct but the result did not appear as I wanted 0.05. The issue was my lack of understanding about how Scheme deals with rationals and integers, not Scheme per se. Think in terms of formatting (how the result appears) and what we see makes sense. Scheme is very powerful in terms of it accuracy  don't know how many numbers after the decimal it is capable of determining but it is large. pi ; returns 3.141592653589793 while I was able to coax one more digit of precision with this (/ 3 2.12345678912345678 ) ; ==> 1.4127906983397445 (quotient 1 2) should return an integer result 0 and not a rational like 1/2. This procedure *should* be used carefully to make certain rounding errors are not exaggerated. For example: (* (quotient 3 2) 2) ;==> 2 and not 3 as you might expect. You can accommodate the appearance of the end computational result by applying various rounding procedures (help contains references to many) or by artificially inflating the values used in certain procedures. Eg: (/ (* (quotient 30 2) 2) 10) ; ==> 3 The following code is not my all own work (pinched a lot from QUT lecture material) but it may help you understand rationals (in Scheme) a little better. At least it did for me  BTW, the material was presented in the context of data abstraction. This was a real "lights flashing" moment for me  I hope it is of some help for you. Kindest regards, Mike ; The following procedures represent rational numbers as two integers (define [makerat n d] (list (/ n (gcd n d)) ; ; Construct rational n/d (/ d (gcd n d)))) ; gcd = greatest common denominator (define [numer x] ; Select numerator of rational x (first x)) (define [denom x] ; Select denominator of x (second x)) ; Since the procedures above do exactly the same thing ; as the corresponding list operations, ; we can equivalently define them as follows: (define makerat list) (define numer first) (define denom second) ; Displaying rational numbers ; In the case of rational numbers we can show them as a string ; consisting of the numerator, followed by a '/', ; followed by the denominator (define [showrat x] (stringappend (number>string (numer x)) "/" (number>string (denom x)))) ; Example: ;(showrat (makerat 1 3)) ; returns "1/3" ; I M P O R T A N T B A S I C S ; The rules of rational number arithmetic ; The following equalities describe arithmetic in terms of ; numerators and denominators ; n1/d1 + n2/d2 = (n1d2 + n2d1)/d1*d2 ; n1/d1  n2/d2 = (n1d2  n2d1)/d1*d2 ; (n1/d1)/(n2/d2) = n1*d2/d1*n2 ; (n1/d1) * (n2/d2) = n1*n2/d1*d2 ; n1/d1 = n2/d2 iff n1d2 = n2d1 ; Note the closure propertyeach operator takes two ; rational numbers and returns a rational number ; Operations for rational number arithmetic ; We can define these operations easily using the ; rational number constructor and selectors we defined earlier (define [addrat x y] (makerat (+ (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define [subrat x y] (makerat ( (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define [mulrat x y] (makerat (* (numer x) (numer y)) (* (denom x) (denom y)))) (define [divrat x y] (makerat (* (numer x) (denom y)) (* (numer y) (denom x)))) ; A predicate for rational numbers ; The following property defines equality for rational numbers ; n1/d1 = n2/d2 iff n1d2 = n2d1 ; This property can be expressed easily as a ; Booleanvalued procedure (define [equalrat? x y] (= (* (numer x) (denom y)) (* (numer y) (denom x)))) ; Representing rational numbers consistently ; Our rational number representations will not ; always be the simplest: (define onethird (makerat 1 3)) ;(showrat (addrat ; onethird onethird)) ;returns "6/9" ; We would prefer the result to be "2/3" in this case ; We can solve this by dividing the numerator and ; denominator by their greatest common divisor (gcd) ; when we construct a rational number: (define [makerat n d] (list (/ n (gcd n d)) (/ d (gcd n d)))) ; (The Scheme gcd procedure for calculating greatest ; common divisors using Euclid's algorithm is in ; Structure and Interpretation of Computer Programs, Section 1.2.5) ;(showrat (addrat ; onethird onethird)) ;returns "2/3" ; Data abstraction barriers ; ; When designing a data abstraction we should consider ; carefully the interface between the concrete data ; representation and the user of the abstraction ; Welldesigned interfaces make programs easier to ; understand because higher levels of abstraction get ; a simplified view of compound data objects ; Welldesigned interfaces also make programs easier ; to maintain by isolating the effects of changes to ; concrete data representations. ; For example: ; Data abstraction barriers in the rational number case study ; ; PROGRAMS THAT USE RATIONAL NUMBERS ;  ;  ; Rational numbers in the problem domain ; ; ADDRAT SUBRAT ... ;  ;  ; Rational numbers as numerators and denominators ; ; MAKERAT NUMER DENOM ;  ;  ; Rational numbers as lists ; ; CONS FIRST SECOND ... ;  ;  ; Scheme's implentation of lists ; ; ; Isolating the effects of change ; (1) Earlier we saw how the makerat constructor could be ; modified so that the underlying representation of rational ; numbers was always reduced to its lowest terms ; (2) Alternatively, we could leave makerat in its original ; form and instead calculate the lowest terms in selector ; procedures numer and denom ; (3) The concrete representation of rational numbers ; like 6/9 is different in these two approaches, ; but this difference is invisible to the higher abstraction level [...snip...]  when I divide using   (/ 1 2)   or   (quotient 1 2)   I get 1/2.   When I divide using   (/ 1 2.)   I get 0.5   As I want to use this to calculate Taylor series and other such  sequences, I really need the decimal representation. How do I coerce  this (do I need to coerce it or is this much simpler)?   For example, if I   (define series  (lambda (x)  (/ 1 x)))   and then do   (map series '(1 2 3 4 5))   I get a list of ones as a result. That's not right ;) It seems as  though there's a simple concept here that I'm unaware of. Tell me  what it is, please!





