1. BUG! Erratic for loop behavior
- Posted by Andy Serpa <renegade at earthling.net> Mar 23, 2002
- 502 views
Hello, The output of this loop: ------------------------------ for i = 9.4 to 10.0 by .1 do ? i end for ------------------------------ stops at 10, as expected. The output of this loop: ------------------------------ for i = 31.1 to 34.2 by .1 do ? i end for ------------------------------ stops at 34.1 (!), NOT as expected. The output of this loop: ------------------------------ for i = 131.1 to 134.2 by .1 do ? i end for ------------------------------ stops at 134.2, as expected. The output of this loop: ------------------------------ for i = 60.0 to 64.5 by .1 do ? i end for ------------------------------ stops at 64.4, NOT as expected. I've verified this on exw.exe & ex.exe, as well as translated to C. It looks like an outright bug to me.
2. Re: BUG! Erratic for loop behavior
- Posted by Rolf Schröder <r.schr at t-online.de> Mar 23, 2002
- 457 views
Andy Serpa wrote: > ... > ------------------------------ > for i = 31.1 to 34.2 by .1 do > ? i > end for > ------------------------------ > stops at 34.1 (!), NOT as expected. > Hi Andy, that's ok. Look at this: for i = 31.1 to 34.1 by 0.1 do printf(1,"%20.15f\n",i) end for and you will notice why: the decimal given value 0.1 is exactly representable in the computer for it has to stores it internally as an binary value with a limited number of bits. Actually, 0.1 (dec.) is has an unlimited binary representation: 0.0001100110011..... . This is the correct way to do it (have in mind that 31.1 and 34.1 are also not exactly representable!): for i = 311 to 341 by 1 do printf(1,"%20.15f\n",i/10) end for Have a nice day, Rolf
3. Re: BUG! Erratic for loop behavior
- Posted by Rolf Schröder <r.schr at t-online.de> Mar 23, 2002
- 471 views
"Rolf Schröder" wrote: > .. > ... the decimal given value 0.1 is exactly > representable ... It should be: ... the decimal given value 0.1 is NOT exactly reresentable ... . Sorry, Rolf
4. Re: BUG! Erratic for loop behavior
- Posted by rforno at tutopia.com Mar 23, 2002
- 462 views
Of course you are right. The desirable behavior is that lost precision does not interfere with exact results. But the solution to this problem is costly in processing time. Should Euphoria fix it, it would be much slower. There are a couple of programming languages where this problem does not practically exist. These are APL (in which a fuzz is considered in comparisons) and ABC (a language from the Netherlands, which does arithmetic with [nearly] infinite digits, and that does not lose precision even after assigning a number such as 0.3 to a variable). But they are much slower than Euphoria. Regards. ----- Original Message ----- From: "Andy Serpa" <renegade at earthling.net> To: "EUforum" <EUforum at topica.com> Subject: RE: BUG! Erratic for loop behavior > > Here's another example: > > atom sum > sum = 60.0 > > for i = 1 to 45 do > sum += .1 > end for > ? sum > ? equal(sum,64.5) > ? (sum = 64.5) > Output is: > > 64.5 > 0 > 0 > > Please don't tell me this is desirable behavior. Explaining the cause > of the problem doesn't remove the problem. I am well aware of how > computers represent numbers but since I'm only dealing with one decimal > place I should get at least that much precision (actually, reverse that > -- I am getting too much precision) when doing comparsions... > > > Andy Serpa wrote: > > > > Rolf Schröder wrote: > > > Andy Serpa wrote: > > > > ... > > > > ------------------------------ > > > > for i = 31.1 to 34.2 by .1 do > > > > ? i > > > > end for > > > > ------------------------------ > > > > stops at 34.1 (!), NOT as expected. > > > > > > > Hi Andy, > > > > > > that's ok. Look at this: > > > > > > for i = 31.1 to 34.1 by 0.1 do > > > printf(1,"%20.15f\n",i) > > > end for > > > > > > and you will notice why: the decimal given value 0.1 is exactly > > > representable in the computer for it has to stores it internally as an > > > binary value with a limited number of bits. Actually, 0.1 (dec.) is has > > > an unlimited binary representation: 0.0001100110011..... . This is the > > > correct way to do it (have in mind that 31.1 and 34.1 are also not > > > exactly representable!): > > > > > > for i = 311 to 341 by 1 do > > > printf(1,"%20.15f\n",i/10) > > > end for > > > > > > > Yeah, that's not really good enough for me -- .1 should be .1 in a loop. > > The Euphoria manual even has an example under the FOR loop section > > using a .3 "by" value... Is this also a "feature"? > > > > > > >
5. Re: BUG! Erratic for loop behavior
- Posted by petelomax at blueyonder.co.uk Mar 23, 2002
- 472 views
On Sat, 23 Mar 2002 20:36:14 +0100, Rolf Schröder <r.schr at t-online.de> wrote: >Actually, 0.1 (dec.) is has >an unlimited binary representation: 0.0001100110011..... . Sanity check required. Kinda understand. Kinda appreciate I may have been mollycoddled over many years, or somesuch. Where'd you get this from, please. Pete
6. Re: BUG! Erratic for loop behavior
- Posted by petelomax at blueyonder.co.uk Mar 23, 2002
- 488 views
On Sat, 23 Mar 2002 22:18:30 +0000, Chris Bensler <bensler at mail.com> wrote: > >Do a search for "floating point precision" in the mailing list archives. Heh heh hey, 5,247 messages! Pete d8=
7. Re: BUG! Erratic for loop behavior
- Posted by Dan Moyer <DANIELMOYER at prodigy.net> Mar 23, 2002
- 463 views
Andy, Although I assume this is at least obvious, you could just do this: for i = 10*31.1 to 10*34.2 do ?i/10 end for Same for whatever max "level" of floating point you have, ie, if *any* value goes out to .001,multiply all by 1000, then divide, etc. Maybe there's some good reason that doesn't occur to me offhand why this won't work? Dan Moyer ----- Original Message ----- From: "Andy Serpa" <renegade at earthling.net> To: "EUforum" <EUforum at topica.com> Sent: Saturday, March 23, 2002 11:19 AM Subject: BUG! Erratic for loop behavior > > Hello, > > > The output of this loop: > ------------------------------ > for i = 9.4 to 10.0 by .1 do > ? i > end for > ------------------------------ > stops at 10, as expected. > > > The output of this loop: > ------------------------------ > for i = 31.1 to 34.2 by .1 do > ? i > end for > ------------------------------ > stops at 34.1 (!), NOT as expected. > > > The output of this loop: > ------------------------------ > for i = 131.1 to 134.2 by .1 do > ? i > end for > ------------------------------ > stops at 134.2, as expected. > > > The output of this loop: > ------------------------------ > for i = 60.0 to 64.5 by .1 do > ? i > end for > ------------------------------ > stops at 64.4, NOT as expected. > > > I've verified this on exw.exe & ex.exe, as well as translated to C. It > looks like an outright bug to me. >
8. Re: BUG! Erratic for loop behavior
- Posted by Dan Moyer <DANIELMOYER at prodigy.net> Mar 23, 2002
- 480 views
off the top of my head: change the vars to sequence, check for '.', count how many to right of '.', multiply by 10 to the how many for the MAX number in any var? Dan ----- Original Message ----- From: "Chris Bensler" <bensler at mail.com> To: "EUforum" <EUforum at topica.com> Subject: RE: BUG! Erratic for loop behavior > > for i = var1 to var 2 by var3 do > end for > > how much should the vars be multiplied by? > > Chris > > Dan Moyer wrote: > > Andy, > > > > Although I assume this is at least obvious, you could just do this: > > > > for i = 10*31.1 to 10*34.2 do > > ?i/10 > > end for > > > > Same for whatever max "level" of floating point you have, ie, if *any* > > value > > goes out to .001,multiply all by 1000, then divide, etc. > > > > Maybe there's some good reason that doesn't occur to me offhand why this > > won't work? > > > > Dan Moyer > > > > ----- Original Message ----- > > From: "Andy Serpa" <renegade at earthling.net> > > To: "EUforum" <EUforum at topica.com> > > Sent: Saturday, March 23, 2002 11:19 AM > > Subject: BUG! Erratic for loop behavior > > > > > > > Hello, > > > > > > > > > The output of this loop: > > > ------------------------------ > > > for i = 9.4 to 10.0 by .1 do > > > ? i > > > end for > > > ------------------------------ > > > stops at 10, as expected. > > > > > > > > > The output of this loop: > > > ------------------------------ > > > for i = 31.1 to 34.2 by .1 do > > > ? i > > > end for > > > ------------------------------ > > > stops at 34.1 (!), NOT as expected. > > > > > > > > > The output of this loop: > > > ------------------------------ > > > for i = 131.1 to 134.2 by .1 do > > > ? i > > > end for > > > ------------------------------ > > > stops at 134.2, as expected. > > > > > > > > > The output of this loop: > > > ------------------------------ > > > for i = 60.0 to 64.5 by .1 do > > > ? i > > > end for > > > ------------------------------ > > > stops at 64.4, NOT as expected. > > > > > > > > > I've verified this on exw.exe & ex.exe, as well as translated to C. It > > > looks like an outright bug to me. > > > > > > > >
9. Re: BUG! Erratic for loop behavior
- Posted by Dan Moyer <DANIELMOYER at prodigy.net> Mar 23, 2002
- 485 views
Chris, Oops, I meant "change the var which was a number into a STRING...", then look for the decimal point in that string, then see which var has the most places to the right of the decimal point, and use that X10 as the multiplier. example code: -- begin code: include misc.e integer multiplier, PosOfDecPoint multiplier = 1 PosOfDecPoint= 0 atom var1, var2, var3 var1 = 31.1 var2 = 34.25 var3 = .01 sequence tempVar1, tempVar2, tempVar3 tempVar1 = sprint(var1) tempVar2= sprint(var2) tempVar3 = sprint(var3) PosOfDecPoint = find('.', tempVar1) if PosOfDecPoint then if length(tempVar1) - PosOfDecPoint > multiplier then multiplier = length(tempVar1) - PosOfDecPoint end if end if PosOfDecPoint = find('.', tempVar2) if PosOfDecPoint then if length(tempVar1) - PosOfDecPoint > multiplier then multiplier = length(tempVar2) - PosOfDecPoint end if end if PosOfDecPoint = find('.', tempVar3) if PosOfDecPoint then if length(tempVar1) - PosOfDecPoint > multiplier then multiplier = length(tempVar3) - PosOfDecPoint end if end if for i = multiplier*var1 to multiplier*var2 by multiplier*var3 do puts(1, sprint(i/multiplier) & " ") end for -- end code Dan ----- Original Message ----- From: "Dan Moyer" <DANIELMOYER at prodigy.net> To: "EUforum" <EUforum at topica.com> Sent: Saturday, March 23, 2002 9:26 PM Subject: Re: BUG! Erratic for loop behavior > > off the top of my head: > change the vars to sequence, check for '.', count how many to right of '.', > multiply by 10 to the how many for the MAX number in any var? > > Dan > > ----- Original Message ----- > From: "Chris Bensler" <bensler at mail.com> > To: "EUforum" <EUforum at topica.com> > Sent: Saturday, March 23, 2002 9:02 PM > Subject: RE: BUG! Erratic for loop behavior > > > > for i = var1 to var 2 by var3 do > > end for > > > > how much should the vars be multiplied by? > > > > Chris > > > > Dan Moyer wrote: > > > Andy, > > > > > > Although I assume this is at least obvious, you could just do this: > > > > > > for i = 10*31.1 to 10*34.2 do > > > ?i/10 > > > end for > > > > > > Same for whatever max "level" of floating point you have, ie, if *any* > > > value > > > goes out to .001,multiply all by 1000, then divide, etc. > > > > > > Maybe there's some good reason that doesn't occur to me offhand why this > > > won't work? > > > > > > Dan Moyer > > > > > > ----- Original Message ----- > > > From: "Andy Serpa" <renegade at earthling.net> > > > To: "EUforum" <EUforum at topica.com> > > > Sent: Saturday, March 23, 2002 11:19 AM > > > Subject: BUG! Erratic for loop behavior > > > > > > > > > > Hello, > > > > > > > > > > > > The output of this loop: > > > > ------------------------------ > > > > for i = 9.4 to 10.0 by .1 do > > > > ? i > > > > end for > > > > ------------------------------ > > > > stops at 10, as expected. > > > > > > > > > > > > The output of this loop: > > > > ------------------------------ > > > > for i = 31.1 to 34.2 by .1 do > > > > ? i > > > > end for > > > > ------------------------------ > > > > stops at 34.1 (!), NOT as expected. > > > > > > > > > > > > The output of this loop: > > > > ------------------------------ > > > > for i = 131.1 to 134.2 by .1 do > > > > ? i > > > > end for > > > > ------------------------------ > > > > stops at 134.2, as expected. > > > > > > > > > > > > The output of this loop: > > > > ------------------------------ > > > > for i = 60.0 to 64.5 by .1 do > > > > ? i > > > > end for > > > > ------------------------------ > > > > stops at 64.4, NOT as expected. > > > > > > > > > > > > I've verified this on exw.exe & ex.exe, as well as translated to C. > It > > > > looks like an outright bug to me. > > > > > > >
10. Re: BUG! Erratic for loop behavior
- Posted by Dan Moyer <DANIELMOYER at prodigy.net> Mar 23, 2002
- 485 views
Chris, Oh. Didn't think about how *many* places could be multiplied into integers! Well, I guess the idea is useful up to a point. My code also had an error in it, besides being uninspired and not fully thought out: The line: if length(tempVar1) - PosOfDecPoint > multiplier then should only read like that for the FIRST test, not all three; in each other test, it should be, respectively, if length(tempVar2) - PosOfDecPoint > multiplier then if length(tempVar3) - PosOfDecPoint > multiplier then sorry. corrected code: include misc.e integer multiplier, PosOfDecPoint multiplier = 1 PosOfDecPoint= 0 atom var1, var2, var3 var1 = 31.1 var2 = 34.25 var3 = .01 sequence tempVar1, tempVar2, tempVar3 tempVar1 = sprint(var1) tempVar2= sprint(var2) tempVar3 = sprint(var3) PosOfDecPoint = find('.', tempVar1) if PosOfDecPoint then if length(tempVar1)- PosOfDecPoint > multiplier then multiplier = length(tempVar1)- PosOfDecPoint end if end if PosOfDecPoint = find('.', tempVar2) if PosOfDecPoint then if length(tempVar2)- PosOfDecPoint > multiplier then multiplier = length(tempVar2)- PosOfDecPoint end if end if PosOfDecPoint = find('.', tempVar3) if PosOfDecPoint then if length(tempVar3)- PosOfDecPoint > multiplier then multiplier = length(tempVar3)- PosOfDecPoint end if end if for i = multiplier*var1 to multiplier*var2 by multiplier*var3 do puts(1, sprint(i/multiplier) & " ") end for Dan ----- Original Message ----- From: "Chris Bensler" <bensler at mail.com> To: "EUforum" <EUforum at topica.com> Sent: Saturday, March 23, 2002 9:56 PM Subject: RE: BUG! Erratic for loop behavior > > function magnify(atom a) > sequence str > integer f > str = sprintf("%f",a) > f = find('.',str) > if f then > a *= power(10,length(str)-f) > end if > return a > end function > > It works for up to 6 decimal places. > 34.1234567 will not be fully magnified. > > > Chris > > > Dan Moyer wrote: > > off the top of my head: > > change the vars to sequence, check for '.', count how many to right of > > '.', > > multiply by 10 to the how many for the MAX number in any var? > > > > Dan > > > > ----- Original Message ----- > > From: "Chris Bensler" <bensler at mail.com> > > To: "EUforum" <EUforum at topica.com> > > Sent: Saturday, March 23, 2002 9:02 PM > > Subject: RE: BUG! Erratic for loop behavior > > > > > > > for i = var1 to var 2 by var3 do > > > end for > > > > > > how much should the vars be multiplied by? > > > > > > Chris > > > > > > Dan Moyer wrote: > > > > Andy, > > > > > > > > Although I assume this is at least obvious, you could just do this: > > > > > > > > for i = 10*31.1 to 10*34.2 do > > > > ?i/10 > > > > end for > > > > > > > > Same for whatever max "level" of floating point you have, ie, if *any* > > > > value > > > > goes out to .001,multiply all by 1000, then divide, etc. > > > > > > > > Maybe there's some good reason that doesn't occur to me offhand why this > > > > won't work? > > > > > > > > Dan Moyer
11. Re: BUG! Erratic for loop behavior
- Posted by Rolf Schröder <r.schr at t-online.de> Mar 24, 2002
- 469 views
petelomax at blueyonder.co.uk wrote: > > > On Sat, 23 Mar 2002 20:36:14 +0100, Rolf Schröder <r.schr at t-online.de> > wrote: > > >Actually, 0.1 (dec.) is has > >an unlimited binary representation: 0.0001100110011..... . > > Sanity check required. Kinda understand. Kinda appreciate I may have > been mollycoddled over many years, or somesuch. > > Where'd you get this from, please. > You do it yourself! The decimal 0.1 is equal 1/10 . Written with binary numbers it's 1/1010 . Now you fulfill a 'written' division as you may be used to do for decimal numbers (but now you have only 0 and 1 as digits): 1: 1010 = 0.0001100110011.... ----------- 10: 1010 = 0 --------- 100 : 1010 = 0 ----------- * 1000 : 1010 = 0 ------------ 10000 : 1010 = 1 -1010 ------ 1100 : 1010 = 1 -1010 ------ 100 : 1010 = 0 ---------- 1000 : 1010 = 0 from here the same as (*) and therefore repeated. One has to become familiar with this kind of calculations :) . Have a nice division, Rolf
12. Re: BUG! Erratic for loop behavior
- Posted by Dan Moyer <DANIELMOYER at prodigy.net> Mar 24, 2002
- 482 views
Andy, Got it. I think Kat made a suggestion once for doing "string math" to avoid this problem in general, don't remember if there was a problem or downside other than speed. If it's always/only add/subtract dollars & cents, though, mult/divide everything that's dollars by 100 should work, but multiplication (like but not limited to percents) could become a problem, as Chris pointed out that my solution won't work for 7 places to right of decimal (his mod of his method works up to 9 I think). And I agree that this should be mentioned in the manual, you caught it in time, others might not, although that brings up the question "who reads the fine manual?". :) (actually I refer to it constantly, but that's bad memory at work!) Dan ----- Original Message ----- From: "Andy Serpa" <renegade at earthling.net> To: "EUforum" <EUforum at topica.com> Sent: Saturday, March 23, 2002 10:24 PM Subject: RE: BUG! Erratic for loop behavior > > > Dan Moyer wrote: > > Andy, > > > > Although I assume this is at least obvious, you could just do this: > > > > for i = 10*31.1 to 10*34.2 do > > ?i/10 > > end for > > > > Same for whatever max "level" of floating point you have, ie, if *any* > > value > > goes out to .001,multiply all by 1000, then divide, etc. > > > > > Maybe there's some good reason that doesn't occur to me offhand why this > > won't work? > > > > No, that works fine for getting this particular loop to work. But the > problem outside of a loop as well. Let's say you make an application > that adds and subtracts dollars & cents a lot. > > .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 does not equal 1 -- just try > it. It will display as one if you print it, but if you do this: > > x = .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 + .1 > if x = 1 then > puts(1,"TRUE.") > else > puts(1,"FALSE.") > end if > > It will come up false. > > So if you have a program that does any kind of floating-point > calculations, and then check to see if a particular value = some other > value, you'll often get the wrong answer. > > I just didn't realize before it was so serious. Those of use who don't > come from a low-level programming background or don't have a lot of > hardware knowledge aren't told this anywhere. It really ought to be in > the manual.... > > > >
13. Re: BUG! Erratic for loop behavior
- Posted by petelomax at blueyonder.co.uk Mar 24, 2002
- 474 views
On Sun, 24 Mar 2002 16:45:00 +0000, Chris Bensler <bensler at mail.com> wrote: >This seems like a devastating problem. We use fractional numbers all the >time. How is it possible that it doesn't show up more often? > >Do we need to resort to binary math? Would that even help? > >What can be done to ensure that my program is calculating the math >properly? > See http://www2.hursley.ibm.com/decimal/ I think that's what is needed, There is even some C code there. It is IEEE854 rather than IEEE754. What does everyone else think? I should specifically mention the following extracts: Complaints about the performance of decimal arithmetic are extremely common. Software emulation is 100 to 1000 times slower than a hardware implementation could be. For example, a JIT-compiled 9-digit BigDecimal division in Java takes over 13,000 clock cycles on an Intel Pentium. Even a simple 9-digit decimal addition takes at least 1,100 clock cycles. In contrast, a native hardware decimal type could reduce this to a speed comparable to binary arithmetic (39 cycles). Almost all major IBM language products support decimal arithmetic, including C (as a native data type, on z900), C++ (via libraries), COBOL, Java (through the Sun or IBM BigDecimal class), OS/400 CL, PL/I, PL/X (on AS/400), NetRexx, PSM (in DB2), Rexx, Object Rexx, RPG, and VisualAge Generator. Many other languages also support decimal arithmetic, including Microsoft’s Visual Basic and C# languages (both of which provide a floating-point decimal arithmetic using the .Net runtime Decimal class). Pete
14. Re: BUG! Erratic for loop behavior
- Posted by Rolf Schröder <r.schr at t-online.de> Mar 24, 2002
- 467 views
Chris Bensler wrote: > > I just did some further testing, and it seems that magnifying a decimal > value doesn't help either. > > ? magnify(0.12345678901) = 12345678901 -- 0 > ? magnify(0.12345678901) = 123456789 -- 0 > ? magnify(0.12345678901) = 12345679 -- 0 > Chris, it's the truth for all computer languages: unlimited binary numbers (like 1/1010) are not exactly representable by floating point numbers. Be aware there are even more numbers not exactly representable for calculating machines, like sqrt(2) or exp(1)... . But there are languages like 'Mathematica' or 'Derive' especially designed to fulfill so called 'algebraic computations' similar like humans do it after known rules. But they are slow and not useful for 'number crunching'. However, for the 'normal' purposes in techniques and science, it's not necessary to represent numbers exactly, it's sufficient to have a relative accuracy of 15 decimal digits. All known physical constants do have only an accuracy of about 4 to 7 decimal digits, not more! But of course one has to be careful to avoid introducing a loss of accuracy in calculations, i.e. small differences of large numbers! You may have always a small loss of accuracy in your programs, Rolf
15. Re: BUG! Erratic for loop behavior
- Posted by jbrown1050 at yahoo.com Mar 24, 2002
- 474 views
--x+6KMIRAuhnl3hBn I have a hack which works fairly well, depending on the accuracy you want. It is a big hack, and not a long-term solution, but at least it works. It works by converting a number to a string and back again. Also, it needs a modified get.e, else inf and nan tests dont work at all. jbrown --x+6KMIRAuhnl3hBn Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="test.ex" -- file which uses a hack to fix problems with floating-point numbers and nan include get.e include misc.e function num_to_str(atom a) return sprint(a) end function function str_to_num(sequence s) sequence t t = value(s) if t[1] = GET_SUCCESS and atom(t[2]) then return t[2] end if return 0 end function global function fix_num(atom a) --this is the hack which "fixes" a number to its proper value. a = str_to_num(num_to_str(a)) return a end function global constant inf = 2*power(10, 308), nan = -(inf/inf) --test atom a a = 0 for i = 1 to 10 do a += .1 end for ? a ? fix_num(a) = 1 a = -(inf/inf) ? a ? fix_num(a) = fix_num(nan) --this doesnt work w/o the modified get.e --x+6KMIRAuhnl3hBn Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="get.e" ------------------------------------ -- Input and Conversion Routines: -- -- get() -- -- value() -- -- wait_key() -- ------------------------------------ -- needed to check for nan and inf in input data constant gnan=-(2*power(10,308)/(3*power(10,308))), ginf=2*power(10,308) -- error status values returned from get() and value(): global constant GET_SUCCESS = 0, GET_EOF = -1, GET_FAIL = 1 constant M_WAIT_KEY = 26 constant DIGITS = "0123456789", HEX_DIGITS = DIGITS & "ABCDEF", START_NUMERIC = DIGITS & "-+.#" constant TRUE = 1 type natural(integer x) return x >= 0 end type type char(integer x) return x >= -1 and x <= 255 end type natural input_file -- file to be read from object input_string -- string to be read from natural string_next char ch -- the current character global function wait_key() -- Get the next key pressed by the user. -- Wait until a key is pressed. return machine_func(M_WAIT_KEY, 0) end function procedure get_ch() -- set ch to the next character in the input stream (either string or file) if sequence(input_string) then if string_next <= length(input_string) then ch = input_string[string_next] string_next += 1 else ch = GET_EOF end if else ch = getc(input_file) end if end procedure procedure skip_blanks() -- skip white space -- ch is "live" at entry and exit while find(ch, " \t\n\r") do get_ch() end while end procedure constant ESCAPE_CHARS = "nt'\"\\r", ESCAPED_CHARS = "\n\t'\"\\\r" function escape_char(char c) -- return escape character natural i i = find(c, ESCAPE_CHARS) if i = 0 then return GET_FAIL else return ESCAPED_CHARS[i] end if end function function get_qchar() -- get a single-quoted character -- ch is "live" at exit char c get_ch() c = ch if ch = '\\' then get_ch() c = escape_char(ch) if c = GET_FAIL then return {GET_FAIL, 0} end if elsif ch = '\'' then return {GET_FAIL, 0} end if get_ch() if ch != '\'' then return {GET_FAIL, 0} else get_ch() return {GET_SUCCESS, c} end if end function function get_string() -- get a double-quoted character string -- ch is "live" at exit sequence text text = "" while TRUE do get_ch() if ch = GET_EOF or ch = '\n' then return {GET_FAIL, 0} elsif ch = '"' then get_ch() return {GET_SUCCESS, text} elsif ch = '\\' then get_ch() ch = escape_char(ch) if ch = GET_FAIL then return {GET_FAIL, 0} end if end if text = text & ch end while end function type plus_or_minus(integer x) return x = -1 or x = +1 end type function get_number() -- read a number -- ch is "live" at entry and exit plus_or_minus sign, e_sign natural ndigits integer hex_digit atom mantissa, dec, e_mag sign = +1 mantissa = 0 ndigits = 0 -- process sign if ch = '-' then sign = -1 get_ch() elsif ch = '+' then get_ch() end if if ch = 'n' then get_ch() if ch = 'a' then get_ch() if ch = 'n' then return {GET_SUCCESS, gnan*sign} else return {GET_FAIL, 0} end if else return {GET_FAIL, 0} end if end if if ch = 'i' then get_ch() if ch = 'n' then get_ch() if ch = 'f' then return {GET_SUCCESS, ginf*sign} else return {GET_FAIL, 0} end if else return {GET_FAIL, 0} end if end if -- get mantissa if ch = '#' then -- process hex integer and return get_ch() while TRUE do hex_digit = find(ch, HEX_DIGITS)-1 if hex_digit >= 0 then ndigits += 1 mantissa = mantissa * 16 + hex_digit get_ch() else if ndigits > 0 then return {GET_SUCCESS, sign * mantissa} else return {GET_FAIL, 0} end if end if end while end if -- decimal integer or floating point while ch >= '0' and ch <= '9' do ndigits += 1 mantissa = mantissa * 10 + (ch - '0') get_ch() end while if ch = '.' then -- get fraction get_ch() dec = 10 while ch >= '0' and ch <= '9' do ndigits += 1 mantissa += (ch - '0') / dec dec *= 10 get_ch() end while end if if ndigits = 0 then return {GET_FAIL, 0} end if mantissa = sign * mantissa if ch = 'e' or ch = 'E' then -- get exponent sign e_sign = +1 e_mag = 0 get_ch() if ch = '-' then e_sign = -1 get_ch() elsif ch = '+' then get_ch() end if -- get exponent magnitude if ch >= '0' and ch <= '9' then e_mag = ch - '0' get_ch() while ch >= '0' and ch <= '9' do e_mag = e_mag * 10 + ch - '0' get_ch() end while else return {GET_FAIL, 0} -- no exponent end if e_mag *= e_sign if e_mag > 308 then -- rare case: avoid power() overflow mantissa *= power(10, 308) if e_mag > 1000 then e_mag = 1000 end if for i = 1 to e_mag - 308 do mantissa *= 10 end for else mantissa *= power(10, e_mag) end if end if return {GET_SUCCESS, mantissa} end function function Get() -- read a Euphoria data object as a string of characters -- and return {error_flag, value} -- Note: ch is "live" at entry and exit of this routine sequence s, e skip_blanks() if find(ch, START_NUMERIC) then return get_number() elsif ch = '{' then -- process a sequence s = {} get_ch() skip_blanks() if ch = '}' then get_ch() return {GET_SUCCESS, s} -- empty sequence end if while TRUE do e = Get() -- read next element if e[1] != GET_SUCCESS then return e end if s = append(s, e[2]) skip_blanks() if ch = '}' then get_ch() return {GET_SUCCESS, s} elsif ch != ',' then return {GET_FAIL, 0} end if get_ch() -- skip comma end while elsif ch = '\"' then return get_string() elsif ch = '\'' then return get_qchar() elsif ch = -1 then return {GET_EOF, 0} else return {GET_FAIL, 0} end if end function global function get(integer file) -- Read the string representation of a Euphoria object -- from a file. Convert to the value of the object. -- Return {error_status, value}. input_file = file input_string = 0 get_ch() return Get() end function global function value(sequence string) -- Read the representation of a Euphoria object -- from a sequence of characters. Convert to the value of the object. -- Return {error_status, value). input_string = string string_next = 1 get_ch() return Get() end function global function prompt_number(sequence prompt, sequence range) -- Prompt the user to enter a number. -- A range of allowed values may be specified. object answer while 1 do puts(1, prompt) answer = gets(0) -- make sure whole line is read puts(1, '\n') answer = value(answer) if answer[1] != GET_SUCCESS or sequence(answer[2]) then puts(1, "A number is expected - try again\n") else if length(range) = 2 then if range[1] <= answer[2] and answer[2] <= range[2] then return answer[2] else printf(1, "A number from %g to %g is expected here - try again\n", range) end if else return answer[2] end if end if end while end function global function prompt_string(sequence prompt) -- Prompt the user to enter a string object answer puts(1, prompt) answer = gets(0) puts(1, '\n') if sequence(answer) and length(answer) > 0 then return answer[1..length(answer)-1] -- trim the \n else return "" end if end function global function get_bytes(integer fn, integer n) -- Return a sequence of n bytes (maximum) from an open file. -- If n > 0 and fewer than n bytes are returned, -- you've reached the end of file. -- This function is normally used with files opened in binary mode. sequence s integer c if n = 0 then return {} end if c = getc(fn) if c = -1 then return {} end if s = repeat(c, n) for i = 2 to n do s[i] = getc(fn) end for if s[n] != -1 then return s else -- trim eof's while s[n] = -1 do n -= 1 end while return s[1..n] end if end function -- This file (unless modified) is FREE - 0 statements. --with 234268341 -- delete this statement if it causes an error --x+6KMIRAuhnl3hBn--
16. Re: BUG! Erratic for loop behavior
- Posted by rolf.schroeder at desy.de Mar 25, 2002
- 475 views
dm31 at uow.edu.au wrote: > ... > an example is the 0.1 is stored as 1 x 10^-1 > thus the mantissa is 1 and the exponent is -1 > ... That's not the truth! Mantissa and exponent each are stored as BINARY numbers, NOT decimal! o.1 decimal is binary (unlimited): 0.000110011001100... which is stored as 0.110011001100... -1000 , (mantissa) (exponent) the usual way to store floating point numbers. Note: the mantissa is cut due to the limited number of bytes available; it means not exactly! Look here for more details: http://www.psc.edu/general/software/packages/ieee/ieee.html Have a nice day, Rolf
17. Re: BUG! Erratic for loop behavior
- Posted by petelomax at blueyonder.co.uk Mar 25, 2002
- 467 views
On Mon, 25 Mar 2002 11:04:25 +1000, dm31 at uow.edu.au wrote: >an example is the 0.1 is stored as 1 x 10^-1 >thus the mantissa is 1 and the exponent is -1 >so using a 8-bit float as an example 0.1 in binary is > >0001 and 1111(-1 in 2's complement) > >So storing numbers like 0.1, 0.3 and 0.01 completely accurately should >not be a problem. It is only a problem in 'larger' decimal numbers. > >for i = 31.4 to 31.5 do... should work perfectly. Or am I just been >dumb? Possibly the latter IEEE 754 floating point numbers are held in binary math, ie <sign>*<mantissa>*2^<exponent>. Yes, that's powers of 2, not 10. This means that 0.1 *CANNOT* be held, the closest you get is about 0.100000000149 Read all about the only alternative I've found at http://www2.hursley.ibm.com/decimal/ Pete