The FooDoo Lounge

Numeric sub-routines

A few things Nigel Garvey has helped me whip into shape. Nigel, and others who understand these these things far better than me, have posted some great stuff to MacScripter. Check it out for more of this kind of thing.

Convert a number in bytes to a readable string

Turn a byte number into a readable string, meant for file sizes. Not terribly accurate for a sum of lots of small files, (due to block size issues, not a bug in this), but good for any single file, or small number of files.

USAGE: set fileSizeString to convertByteSize on 7561726
        --> "7.21 MB"

Input: integer or integral real - a number of bytes. Accepts scientific notation, i.e 7.561726E+6.
Output: string - the byte size returned in bytes, KB, MB, or GB as appropriate.
Error: non-numeric values, non integral reals. Propagates any error without traps. No input class checks.

-- convertByteSize -- by Nigel Garvey & Richard Morton, 2002 --
-- Convert bytes to a readable string in bytes-K-MB-GB as required.
-- Pass the number in bytes. Returns string.
to convertByteSize on theRawSize
    set oneK to 2 ^ 10
    set oneMB to 2 ^ 20
    set oneGB to 2 ^ 30
    tell theRawSize to ¬
        if it oneGB then
            return ((it div oneGB) & "." & text 2 thru 3 of ((100 + ((it mod oneGB) div (oneK * 1.0E+4))) as string) & " GB") as string
        else if it oneMB then
            return ((it div oneMB) & "." & text 2 thru 3 of ((100 + ((it mod oneMB) div (oneK * 10))) as string) & " MB") as string
        else if it oneK then
            return (it div oneK & " KB") as string
        else
            return (it & " bytes") as string
        end if
end convertByteSize

Convert a time in seconds to days-hours-minutes-seconds

Return a time string in hours, minutes & seconds, from a time in seconds using the supplied separator character. Supports days up to 99 and only includes them if the time is one day or more. This is an updated version from NG on 11 April 2003.

USAGE: set timeString to elapsedTime from 8.639999E+6 against ":"
        --> "99:23:59:59"

Input:
        secondTime integer or integral real - the time, in seconds, to convert.
        sepChar string - the separator character for the returned time string.
Output: string - an hours:minutes:seconds OR days:hours:minutes:seconds value.
Error: non numeric or non integral values.

-- elapsedTime -- by Nigel Garvey & Richard Morton, 2002-2003 --
-- Pass an integral value (handles reals) - the time in seconds - and
-- a separator character. Returns string.
on elapsedTime from secondTime against sepChar
    set hms to (1000000 + secondTime mod days div hours * 10000 + ¬
        secondTime mod hours div minutes * 100 + ¬
        secondTime mod minutes div 1) as string
    set hms to text 2 thru 3 of hms & sepChar & ¬
        text 4 thru 5 of hms & sepChar & ¬
        text 6 thru 7 of hms
    if secondTime < days then return hms
    return text 2 thru 3 of ((100 + secondTime div days) as string) & sepChar & hms
end elapsedTime

x!

Just a rewrite of an example I saw in C. A classic recursive algorithm. Don't think about it too hard...

on factorial from n
    if n = 0 then return 1
    return n * (factorial from (n - 1))
end factorial

Round and truncate a number

Round & truncate a number to the specified number of places. This is an adaption of one of NG's handlers and was taken from 'aRounderRound', an excellent set of rouding handlers that is, I believe, available on MacScripter. A nice example of Nigel's innovative tell techniques. Susceptible to AS's floating point bugs, but works for numbers up to 536870911 - see below.

USAGE: set roundedNum to roundTrunc from 6.78905432 for 4
        --> 6.7891

Input:
        n real - the number to round & truncate
        decPlaces integer - the number of decimal places to round to.
Output: real - the rounded & truncated number. Always rounds 5 upwards.
Error: non-numeric values

-- roundTrunc -- by Nigel Garvey & Richard Morton, 2001 --
-- Round and truncate a real to the required number of decimal places.
-- Pass a real & the number of decimal places to return (integer).
-- Returns real. 0.5 rounds up.
on roundTrunc from n for decPlaces
    tell 10 ^ decPlaces
        tell n * it to it div 0.5 - it div 1
        return result / it
    end tell
end roundTrunc

Round and truncate to 2 decimal places

NG sent me this to fix a bug in TaxCalc. Many versions of AS have floating point problems with certain numbers and this works around the known ones. This is as written and includes Nigel's comments, which may help in understanding what he's done. Very clever.

-- roundCurrency -- by Nigel Garvey, 18Jun2002
-- Round and truncate a real to 2 decimal places.
to roundCurrency from n
    -- Multiply by (root-10 squared) times 10 (not by 100) and round off
    tell n * ((10 ^ 0.5) ^ 2) * 10 to get (it div 0.5 - it div 1)
    -- Combine the string coercion with some mathematical reduction
    -- to reduce the likelihood of exponential formatting (which happens if
    -- the whole-number part of the result exceeds 536870911 (AS 1.3.7))
    return (((result div 100) as string) & "." & text 2 thru 3 of ((result mod 100 + 100) as string))
end roundCurrency

 

The FooDoo Lounge is Copyright © Richard Morton 2002-2005

|| url: http://www.foodoo.sunreal.com.au/code/numerics.html
|| created: 27-May-04, 11:48 AM; updated: 27-May-04, 11:47 AM
|| size: 40123 bytes