If speed is important you might want to avoid round n. Because it is an OSAX command, it is much slower than a possible alternative: n as integer.
It looks like prior to AppleScript 1.9.2 (Mac OS X 10.3) coercing a non-integral real number to an integer was an invalid operation (old AppleScript Language Guide: “Only a real value that has no fractional part can be coerced to an integer.”), but these days it rounds (AppleScript 1.9.2 Release Notes: “Real numbers can now be coerced to integers even if they have a non-zero fractional part. Rounding is used to do the coercion.”). I find that as integer seems to round the same way that round n rounding to nearest rounds (including rounding 0.5 to the even side, not always away from zero).
So, I offer the following quarterRounder_3 and some result value comparisons and timing comparisons with cwtnospam’s and Bruce Phillips’s quarter-specific code:
to quarterRounder_1(Num)
set theint to (round Num rounding down)
set thedec to (round ((Num - theint) * 4)) / 4
set thenum to theint + thedec
end quarterRounder_1
to quarterRounder_2(someNumber)
someNumber as integer
return result + ((round ((someNumber - result) * 4) rounding as taught in school) / 4)
end quarterRounder_2
to quarterRounder_3(aNum)
return ((aNum * 4) as integer) / 4 -- In 10.3 and later, "n as integer" is like "round n rounding to nearest" (which is also the default for "round n")
end quarterRounder_3
to testThem(startNum, n, divisor)
script s
property testResults : {}
end script
repeat with testOffset from 0 to n
set testValue to startNum + testOffset / divisor
set {a, b, c} to {quarterRounder_1(testValue), quarterRounder_2(testValue), quarterRounder_3(testValue)}
set allEqual to a = b and b = c
if not allEqual then
set end of s's testResults to {value:testValue, |1|:a, |2|:b, |3|:c}
end if
end repeat
s's testResults
end testThem
to quarterRounder_0(aNum)
aNum
end quarterRounder_0
to timeThem(startNum, n, divisor)
set t0 to current date
repeat with testOffset from 0 to n
set testValue to startNum + testOffset / divisor
quarterRounder_0(testValue)
end repeat
set t1 to current date
repeat with testOffset from 0 to n
set testValue to startNum + testOffset / divisor
quarterRounder_1(testValue)
end repeat
set t2 to current date
repeat with testOffset from 0 to n
set testValue to startNum + testOffset / divisor
quarterRounder_2(testValue)
end repeat
set t3 to current date
repeat with testOffset from 0 to n
set testValue to startNum + testOffset / divisor
quarterRounder_3(testValue)
end repeat
set t4 to current date
set nullTime to t1 - t0
return {base:nullTime, |1|:t2 - t1 - nullTime, |2|:t3 - t2 - nullTime, |3|:t4 - t3 - nullTime}
end timeThem
on run
--return testThem(-2, 4 * 8, 8) -- demonstrate some discrepancies among the algorithms
--> {{value:-1.875, |1|:-2, |2|:-1.75, |3|:-2.0}, {value:-1.125, |1|:-1, |2|:-1.25, |3|:-1.0}, {value:-0.875, |1|:-1, |2|:-0.75, |3|:-1.0}, {value:-0.125, |1|:0, |2|:-0.25, |3|:0.0}, {value:0.125, |1|:0, |2|:0.25, |3|:0.0}, {value:0.875, |1|:1, |2|:0.75, |3|:1.0}, {value:1.125, |1|:1, |2|:1.25, |3|:1.0}, {value:1.875, |1|:2, |2|:1.75, |3|:2.0}}
--return testThem(2.375, 400, 200) -- more individual tests over a smaller numerical domain
--> {{value:2.875, |1|:3, |2|:2.75, |3|:3.0}, {value:3.125, |1|:3, |2|:3.25, |3|:3.0}, {value:3.875, |1|:4, |2|:3.75, |3|:4.0}, {value:4.125, |1|:4, |2|:4.25, |3|:4.0}}
timeThem(2.375, 400, 200)
--> {base:0, |1|:30, |2|:23, |3|:0}
--> {base:0, |1|:34, |2|:24, |3|:0}
--> etc.
end run
For all the values I tested, 1 and 3 effectively return the same value (1 returns an integer when possible, 3 always returns a real). 2 uses a different rounding variation, so it differs on some of the eighths. At least on my machine though the speed difference is immense (1 takes about 30 seconds, 2 a bit less than 30 seconds (only one call to round) for 400 roundings; 3 takes less than 1 second for the same 400 roundings).
Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari Version 3.2.1 (4525.27.1)
Operating System: Mac OS X (10.4)