Mailing List Archive: 49091 messages

# Limiting Precision of Decimals,

### [1/9] from: louisaturk::coxinet::net at: 23-May-2002 21:23

Hi rebols, Is there any way to avoid scientific notation on decimals? For example, I don't want the E-2 at the end of the following number my program has calculated: 6.59262575231111E-2 I want instead: .06592625 <====<<< I would like less precision also. Louis

### [2/9] from: greggirwin:mindspring at: 24-May-2002 16:58

Hi Louis, << Is there any way to avoid scientific notation on decimals? For example, I don't want the E-2 at the end of the following number my program has calculated: >> Here's a rounding function that might do what you want. ; Ladislav Mecir, Gregg Irwin (minor adjustment) mod: func [ {Compute a remainder.} value1 [number! money! time!] {The dividend} value2 [number! money! time!] {The divisor} /euclid {Compute a non-negative remainder such that: a = qb + r and r < b} /local r ] [ either euclid [ either negative? r: value1 // value2 [r + abs value2] [r] ;-- Alternate implementation ;value1 // value2 + (value2: abs value2) // value2 ][ value1 // value2 ] ] ;-- Note: to-interval does mod-like rounding. If the interval you ; specify is not evenly divisble into your base, the result ; may not be what you expect. E.g. round/to-interval 133 30 ; will round to 120, not 130, because 120 is an even multiple ; (read interval) of 30. ; Ladislav Mecir, Gregg Irwin round: func [ {Rounds numeric value with refinements for what kind of rounding you want performed, how many decimal places to round to, etc.} value [number! money! time!] {The value to round} /up {Round away from 0} /floor {Round towards the next more negative digit} /ceiling {Round towards the next more positive digit} /truncate {Remaining digits are unchanged. (a.k.a. down)} /places {The number of decimal places to keep} pl [integer!] /to-interval {Round to the nearest multiple of interval} interval [number! money! time!] /local factor ][ ;-- places and to-interval are redundant. E.g.: ; places 2 = to-interval .01 ; to-interval is more flexible so I may dump places. ;-- This sets factor in one line, under 80 chars, but is it clearer? ;factor: either places [10 ** (- pl)][either to-interval [interval][1]] factor: either places [ 10 ** (negate pl) ] [ either to-interval [interval] [1] ] ;-- We may set truncate, floor, or ceiling in this 'if block. if not any [up floor ceiling truncate] [ ;-- Default rounding is even. Should we take the specified ; decimal places into account when rounding? We do at the ; moment. either (abs value // factor) <> (.5 * factor) [ value: (.5 * factor) + value return value - mod/euclid value factor ] [ ;-- If we get here, it means we're rounding off exactly ; .5 (at the final decimal position that is). either even? value [ truncate: true ] [ either negative? value [floor: true][ceiling: true] ] ] ] if up [either negative? value [floor: true][ceiling: true]] if truncate [return value - (value // factor)] if floor [return value - mod/euclid value factor] if ceiling [return value + mod/euclid (negate value) factor] ] --Gregg

### [3/9] from: louisaturk:eudoramail at: 24-May-2002 20:42

Hi Gregg, Thanks! But I haven't been able to figure out how to use it. Would you please give me a sample usage? Louis At 04:58 PM 5/24/2002 -0600, you wrote:

### [4/9] from: greggirwin:mindspring at: 24-May-2002 21:37

Hi Louis, << Thanks! But I haven't been able to figure out how to use it. Would you please give me a sample usage? >> DOH! I was going to post a simple reply, but it appears you've outsmarted me. :) If there's only a decimal component, and the value is <~.1, REBOL returns it with scientific notation. E.g.
>> round/places/truncate 1.0659262575231111 8
== 1.06592625
>> round/places/truncate .0659262575231111 8
== 6.592625E-2 I'll have to think about this. I'm not sure that I want to scale things internally to work around this issue. Obviously, it should work for all extremes so that's what we'll have to test for in a redesign. Guess it won't work for you right now though. Sorry about that. But, thanks for finding the bug! :) Anyone else listening in? Any thoughts? --Gregg

### [5/9] from: rpgwriter:yah:oo at: 25-May-2002 0:10

--- Gregg Irwin <[greggirwin--mindspring--com]> wrote:
> Hi Louis, > << Thanks! But I haven't been able to figure out
<<quoted lines omitted: 19>>
> bug! :) > Anyone else listening in? Any thoughts?
There's not a bug in your rounding function. As you note, its just a "feature" of the way REBOL converts decimal! values to string! values. There is probably a place for a nice robust function for converting arbitrary values of any type to strings with all kinds of formatting options (sort of an sprintf() for REBOL), but the direct solution to printing decimals to avoid scientific notation for small values is: print-val: either greater? value 0.1 [ to-string value ] [ insert remove to-string 1 + value "0" ] This still has the switch over to scientific notation at values of >= 1E+15. To totally avoid scientific notation, this seems to work (written as a function): dec-to-string: func [ value ] [ z: value w: "" for y to-integer log-10 z 0 -1 [ append w to-string to-integer z / power 10 y z: remainder z power 10 y ] append w remove to-string 1 + remainder z 1 return w ] Chris Dicely

### [6/9] from: g:santilli:tiscalinet:it at: 25-May-2002 12:32

Hi Gregg, On Saturday, May 25, 2002, 5:37:55 AM, you wrote: (CC to Gregg and Luis to avoid list slowness) GI> Anyone else listening in? Any thoughts? Sorry for using a nonstandard style... You should be easily able to fix it for negative numbers (I didn't need them :) and to use different decimal separators (this is for the italian way). form-decimal: func [ num [number!] cifre [integer!] /local str poscifre ] [ ; ***WARNING*** positive numbers only. num: abs num str: make string! 16 either zero? num [ insert str #"0" if cifre > 0 [ insert/dup insert tail str #"," #"0" cifre ] ] [ if 14 < add cifre log-10 num [ return form num] num: form add multiply power 10 cifre to-decimal num 0,5 clear any [find num "." ""] poscifre: skip tail num negate cifre insert/part str num num: skip num 1 + remainder subtract index? poscifre 2 3 while [(index? poscifre) > (index? num)] [ insert/part insert tail str #"'" num num: skip num 3 ] if empty? str [insert str #"0"] if not tail? poscifre [ insert insert/dup insert tail str #"," #"0" cifre - length? poscifre poscifre ] ] str ]
>> form-decimal 1 2
== "1,00"
>> form-decimal 1000 2
== "1'000,00"
>> form-decimal 0.1 2
== "0,10"
>> form-decimal 0.01 2
== "0,01"
>> form-decimal 0.01 5
== "0,01000"
>> form-decimal 0.00001 5
== "0,00001"
>> d: .0659262575231111
== 6.59262575231111E-2
>> form-decimal d 5
== "0,06593" Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

### [7/9] from: rotenca:telvia:it at: 25-May-2002 13:02

Hi Louis and Gregg
> Anyone else listening in? Any thoughts?
Look at Eric Long's http://www.rebol.org/utility/format.r --- Ciao Romano

### [8/9] from: greggirwin:mindspring at: 25-May-2002 12:53

Thanks Chris, Gabriele, and Romano! Louis, it looks like you have a few options to pursue here. I'll be looking into them as well but let me know if, other than formatting, the ROUND function misbehaves. --Gregg

### [9/9] from: louisaturk:eudoramail at: 27-May-2002 20:18

Gregg, Chris, Gabriele, and Romano, Thanks for all the help. I'm still studying your code. I get back with you ASAP (I still have a lot to learn). Louis

Notes
• Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted