Re: 1.0000023E+5 to 100000.23 as text?
Re: 1.0000023E+5 to 100000.23 as text?
- Subject: Re: 1.0000023E+5 to 100000.23 as text?
- From: Nigel Garvey <email@hidden>
- Date: Wed, 13 Dec 2000 11:00:58 +0000
"Mike Miller" wrote on Tue, 12 Dec 2000 14:21:57 -0600:
>
Nigel Garvey <email@hidden> replied:
>
>"Mike Miller" wrote on Mon, 11 Dec 2000 12:37:57 -0600:
>
>>Jason Bourque <email@hidden> asked:
>
>>>How would you go about converting scientific notation into text.
>
>>
>
>>Try the UnScientificNotate AppleScript snippet from the ESG Labs Snippets
>
>>page(...)
>
>
>
>This works very well, but still fails with the problem numbers I
>
>mentioned earlier - such as 8439.39, which comes out as
>
>"8439.389999999999".
>
>
I disagree that this is a failure. The script is successfully doing
>
exactly what it says it will do and no more: you're passing in
>
8439.389999999999, and UnScientificNotate2() gives it right back to you as
>
text.
Yes. Apologies. That was a bad choice of words. I only meant to say that
it doesn't address a relevant problem that occurs elsewhere in the system.
>
>I've now cured the bug in my previous effort and have rethought the logic
>
>so that the relevant bits from the two handlers are combined into one.
>
>Like UnScientificNotate, it produces results that look like integers or
>
>reals, as appropriate, but it can't handle *quite* such large numbers! It
>
>also produces a decimal point character to match the Numbers setting on
>
>the host machine.
>
>
It looks good. I'm guessing numToStr() is faster than
>
UnScientificNotate2(), while USN2 is slightly more complete (USN2 should
>
handle any real you can throw at it, but I haven't spent a whole lot of
>
time testing the two). In most uses, you'd probably pick numToStr().
>
>
However, I couldn't leave UnScientificNotate with the glaring decimal
>
point/comma/whatever issue, so there's a new version of the
>
UnScientificNotate snippet available which should fix that. It also adds
>
RoundToPrecision2(), which fixes some issues with RoundToPrecision and
>
gives you the option to keep trailing zeroes.
I'll look it up today! Meanwhile, it's occurred to me rather belatedly
that as the problem numbers only occur in the range that AppleScript
*doesn't* render in scientific notation, only numbers in this range need
to be multiplied out of the danger area. Shifting any of them by, say,
ten places seems to put them in the E range and all you have to do is
subtract the shift when you decimalise them. The rest, not needing to be
multiplied, can be as large as with UnScientificNotate2()! :-) Back to my
original numToStr() handler with some added twiddly bits:
on numToStr(n)
-- the decimal point character on this machine
set dpChr to the middle character of ((1 / 2) as string)
set zeroStr to "000000000000000000000000000000"
set zeroStrLen to (count zeroStr)
set s to n as string
if s does not contain "E" then
set shift to 10 -- shift left by 10 decimal places to avoid problem
numbers
if n is 0 then
set s to "0.0E+10" -- fix for 0
else
set s to (n * (10 ^ shift)) as string
end if
else
set shift to 0 -- no shift
end if
if n < 0 then set s to text 2 thru -1 of s -- lose any minus sign for
now
set mtLen to (count word 1 of s) - 1 -- length of mantissa
set chrList to characters 1 thru mtLen of s -- the mantissa characters
set item 2 of chrList to "" -- zap the decimal point
-- the target decimal point position (old position + exponent - shift)
set dpPos to 2 + (text (mtLen + 2) thru -1 of s) - shift
if dpPos > 1 then -- ie. the exponent is positive
if item -1 of chrList is "0" then -- fix for single-digit numbers
set {item -1 of chrList, mtLen} to {"", mtLen - 1}
end if
if dpPos does not come before mtLen then -- whole number
if dpPos comes after mtLen then -- append zeros
set z to dpPos - mtLen
repeat (z div zeroStrLen) times
set the end of chrList to zeroStr
end repeat
set the end of chrList to text 1 thru (z mod zeroStrLen) of
zeroStr
end if
if the class of (n as number) is real then
set the end of chrList to dpChr & "0"
end if
else -- insert a decimal point
set item dpPos of chrList to (item dpPos of chrList) & dpChr
end if
else -- negative exponent
if item -1 of chrList is "0" then set item -1 of chrList to ""
set z to 1 - dpPos
repeat (z div zeroStrLen) times
set the beginning of chrList to zeroStr
end repeat
set the beginning of chrList to "0" & dpChr & text 1 thru (z mod
zeroStrLen) of zeroStr
end if
if n < 0 then set the beginning of chrList to "-" -- restore any minus
sign
return chrList as string
end numToStr
NG