Manipulating Numbers
Working with and manipulating numbers is an important and regular occurrence in scripting. Basic mathematic operations—such as addition, subtraction, multiplication, and division—are language-level features, but some other commonly performed operations require custom scripting.
Converting a Number to a String
Scripts often need to convert numbers to string format to display information to the user or populate a document. In AppleScript, this conversion can be accomplished most of the time simply by using the coercion operator as, as shown in Listing 20-1.
APPLESCRIPT
12 as string--> Result: "12"
In JavaScript, the same conversion can be accomplished by calling the toString() method, as shown in Listing 20-2.
JAVASCRIPT
num = 12num.toString()// Result: "12"
Converting a Long Number to a String
In AppleScript, long numeric values are displayed in scientific notation. For example, 1234000000 is displayed by a script as 1.234E+9. When this value is coerced to a string, it becomes: "1.234E+9". The handler in Listing 20-3 converts a number, regardless of length, to a string of numeric characters instead of a numeric string in scientific notation.
APPLESCRIPT
on convertNumberToString(theNumber)set theNumberString to theNumber as stringset theOffset to offset of "E" in theNumberStringif theOffset = 0 then return theNumberStringset thePrefix to text 1 thru (theOffset - 1) of theNumberStringset theConvertedNumberPrefix to ""if thePrefix begins with "-" thenset theConvertedNumberPrefix to "-"if thePrefix = "-" thenset thePrefix to ""elseset thePrefix to text 2 thru -1 of thePrefixend ifend ifset theDecimalAdjustment to (text (theOffset + 1) thru -1 of theNumberString) as numberset isNegativeDecimalAdjustment to theDecimalAdjustment is less than 0if isNegativeDecimalAdjustment thenset thePrefix to (reverse of (characters of thePrefix)) as stringset theDecimalAdjustment to -theDecimalAdjustmentend ifset theDecimalOffset to offset of "." in thePrefixif theDecimalOffset = 0 thenset theFirstPart to ""elseset theFirstPart to text 1 thru (theDecimalOffset - 1) of thePrefixend ifset theSecondPart to text (theDecimalOffset + 1) thru -1 of thePrefixset theConvertedNumber to theFirstPartset theRepeatCount to theDecimalAdjustmentif (length of theSecondPart) is greater than theRepeatCount then set theRepeatCount to length of theSecondPartrepeat with a from 1 to theRepeatCounttryset theConvertedNumber to theConvertedNumber & character a of theSecondParton errorset theConvertedNumber to theConvertedNumber & "0"end tryif a = theDecimalAdjustment and a is not equal to (length of theSecondPart) then set theConvertedNumber to theConvertedNumber & "."end repeat if theConvertedNumber ends with "." then set theConvertedNumber to theConvertedNumber & "0"if isNegativeDecimalAdjustment then set theConvertedNumber to (reverse of (characters of theConvertedNumber)) as stringreturn theConvertedNumberPrefix & theConvertedNumberend convertNumberToString
Listing 20-3 shows how to call the handler in Listing 20-3.
APPLESCRIPT
convertNumberToString(8.72124243234E+11)--> Result: "872124243234"
Adding a Descriptive Suffix to a Number
The handlers Listing 20-5 and Listing 20-6 convert a number to a string and appends a suffix of "st", "nd", "rd", or "th", resulting in strings such as "1st", "2nd", "3rd", and "4th".
APPLESCRIPT
on addDescriptiveSuffixToNumber(theNumber)-- Determine the suffix to add, based on the last two digitsset theLastDigit to theNumber mod 10set theLastTwoDigits to theNumber mod 100set theSuffix to "th"if {1, -1} contains theLastDigit and {11, -11} does not contain theLastTwoDigits thenset theSuffix to "st"else if {2, -2} contains theLastDigit and {12, -12} does not contain theLastTwoDigits thenset theSuffix to "nd"else if {3, -3} contains theLastDigit and {13, -13} does not contain theLastTwoDigits thenset theSuffix to "rd"end if-- Return the number and suffixreturn (theNumber as string) & theSuffixend addDescriptiveSuffixToNumber
JAVASCRIPT
function addDescriptiveSuffixToNumber(num) {// Convert the number to absolute valuevar integer = Math.abs(num)// Determine the suffix to add, based on the last two digitsvar suffix = "th"var lastDigit = integer % 10var lastTwoDigits = integer % 100if (lastDigit === 1 && lastTwoDigits !== 11) {suffix = "st"}else if (lastDigit === 2 && lastTwoDigits !== 12) {suffix = "nd"}else if (lastDigit === 3 && lastTwoDigits !== 13) {suffix = "rd"}// Return the number and suffixreturn num.toString() + suffix}
Listing 20-7 and Listing 20-8 show how to test the handlers in Listing 20-5 and Listing 20-6 by looping through a range of positive and negative numbers.
APPLESCRIPT
set theTestResults to ""repeat with a from -10 to 10set theTestResults to theTestResults & addDescriptiveSuffixToNumber(a)if a is less than 10 then set theTestResults to theTestResults & ", "end repeattheTestResults--> Result: "-10th, -9th, -8th, -7th, -6th, -5th, -4th, -3rd, -2nd, -1st, 0, 1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th"
JAVASCRIPT
var testResults = ""for (var i = -10; i <= 10; i++) {testResults += addDescriptiveSuffixToNumber(i)if (i < 10) {testResults += ", "}}testResults// Result: "-10th, -9th, -8th, -7th, -6th, -5th, -4th, -3rd, -2nd, -1st, 0th, 1st, 2nd, 3rd, 4th, 5th, 6th, 7th, 8th, 9th, 10th"
Listing 20-9 and Listing 20-10 show how to call the handlers in Listing 20-5 and Listing 20-6 to identify positions of items in a list.
APPLESCRIPT
set thePersonList to {"Sal", "Ben", "Chris", "David"}set theListLength to length of thePersonListrepeat with a from 1 to theListLengthset theSuffixedNumber to addDescriptiveSuffixToNumber(a)set thePerson to item a of thePersonListdisplay dialog "The " & theSuffixedNumber & " person in list is " & thePerson & "."end repeat
JAVASCRIPT
var app = Application.currentApplication()app.includeStandardAdditions = truevar personList = ["Sal", "Ben", "Chris", "David"]var listLength = personList.lengthfor (var i = 0; i < listLength; i++) {var suffixedNum = addDescriptiveSuffixToNumber(i + 1)var person = personList[i]app.displayDialog(`The ${suffixedNum} person in list is ${person}.`)}
Adding Leading Zeros to a Number
The handlers in Listing 20-11 and Listing 20-12 convert a number to a string and prepends it with leading zeros until it reaches a certain length. They accept two parameters—the number to add leading zeros to and the maximum number of leading zeros to add. For example, if the maximum number of leading zeros is set to 2, the results range from 001 to 999. If the maximum number of leading zeros is 3, the results range from 0001 to 9999, and so on.
APPLESCRIPT
on addLeadingZerosToNumber(theNumber, theMaxLeadingZeroCount)-- Determine if the number is negativeset isNegative to theNumber is less than 0-- Determine when the maximum number of digits will be reachedset theThreshold to (10 ^ theMaxLeadingZeroCount) as integer-- If the number is shorter than the maximum number of digitsif theNumber is less than theThreshold then-- If the number is negative, convert it to positiveif isNegative = true then set theNumber to -theNumber-- Add the zeros to the numberset theLeadingZeros to ""set theDigitCount to length of ((theNumber div 1) as string)set theCharacterCount to (theMaxLeadingZeroCount + 1) - theDigitCountrepeat theCharacterCount timesset theLeadingZeros to (theLeadingZeros & "0") as stringend repeat-- Make the number negative, if it was previously negativeif isNegative = true then set theLeadingZeros to "-" & theLeadingZeros-- Return the prefixed numberreturn (theLeadingZeros & (theNumber as text)) as string-- If the number is greater than or equal to the maximum number of digitselse-- Return the original numberreturn theNumber as textend ifend addLeadingZerosToNumber
JAVASCRIPT
function addLeadingZerosToNumber(num, maxLeadingZeroCount) {var leadingZeros = ""// Convert the number to absolute valuevar absNum = Math.abs(num)// Determine when the maximum number of digits will be reachedvar threshold = Math.pow(10, maxLeadingZeroCount)// If the number is shorter than the maximum number of digitsif (absNum < threshold) {// Prepare a leading zeros stringvar digitCount = Math.trunc(absNum).toString().lengthvar charCount = maxLeadingZeroCount + 1 - digitCountfor (var i = 0 ; i < charCount; i++) {leadingZeros += "0"}}// Add the zeros to the numbervar result = `${leadingZeros}${absNum}`// Make the number negative, if it was previously negativeif (num < 0) {result = `-${result}`}// Return the prefixed numberreturn result}
Listing 20-13 and Listing 20-14 show how to call the handlers in Listing 20-11 and Listing 20-12.
APPLESCRIPT
addLeadingZerosToNumber(9, 3)--> Result: "0009"
JAVASCRIPT
addLeadingZerosToNumber(9, 3)// Result: "0009"
Comma-Delimiting a Number
The handlers Listing 20-15 and Listing 20-16 comma-delimit a numeric value and converts it to a string.
APPLESCRIPT
on convertNumberToCommaDelimitedString(theNumber)-- Convert the number to a stringset theNumber to convertNumberToString(theNumber)-- Determine the length of the numberset theNumberLength to length of theNumber-- Reverse the number so a comma can be added every 3 digitsset theNumber to (reverse of every character of theNumber) as string-- Loop through the number's digits, add commas, and put the numbers back in the correct orderset theConvertedNumber to ""repeat with a from 1 to theNumberLengthif a is theNumberLength or (a mod 3) is not 0 thenset theConvertedNumber to (character a of theNumber & theConvertedNumber) as stringelseset theConvertedNumber to ("," & character a of theNumber & theConvertedNumber) as stringend ifend repeat-- Return the comma delimited numberreturn theConvertedNumberend convertNumberToCommaDelimitedString
JAVASCRIPT
function convertNumberToCommaDelimitedString(num) {// Convert the number to a stringvar numString = num.toString()if (numString.indexOf("e") != - 1) {numString = convertNumberToString(numString)}// Reverse the number so a comma can be added every 3 digitsnumString = numString.split("").reverse().join("")var numStringWithCommas = ""// Determine the length of the numbervar numStringLength = numString.length// Loop through the number's digits, add commas, and put the numbers back in the correct orderfor (var i = 0; i < numStringLength; i++) {var toPrepend = numString[i]if (i != numStringLength - 1 && ((i + 1) % 3) == 0) {toPrepend = "," + toPrepend}numStringWithCommas = toPrepend + numStringWithCommas}// Return the comma delimited numberreturn numStringWithCommas}
Listing 20-17 and Listing 20-18 shows how to call the handlers in Listing 20-15 and Listing 20-16.
APPLESCRIPT
convertNumberToCommaDelimitedString(872124243234)--> Result: "872,124,243,234"
JAVASCRIPT
convertNumberToCommaDelimitedString(872124243234)// Result: "872,124,243,234"
Determining if a Number is an Odd Number
The handlers in Listing 20-28 and Listing 20-29 determine whether a whole number is even or odd. A returned value of false indicates the passed number is even; a returned value of true indicates the passed number is odd.
APPLESCRIPT
on isNumberOdd(theNumber)if theNumber mod 2 is not 0 thenreturn trueelsereturn falseend ifend isNumberOdd
JAVASCRIPT
function isNumberOdd(num) {return num % 2 !== 0}
Listing 20-30 and Listing 20-31 show how to call the handlers in Listing 20-28 and Listing 20-29.
APPLESCRIPT
isNumberOdd(3)--> Result: true
JAVASCRIPT
isNumberOdd(3)// Result: true
Listing 20-32 and Listing 20-33 show how to call the handlers in Listing 20-28 and Listing 20-29 by prompting the user to enter an even number.
APPLESCRIPT
repeatdisplay dialog "Enter an even integer:" default answer ""tryif text returned of result is not "" then set theNumberProvided to text returned of result as integerif isNumberOdd(theNumberProvided) is false then exit repeatend tryend repeat
JAVASCRIPT
var app = Application.currentApplication()app.includeStandardAdditions = truewhile (true) {var result = app.displayDialog("Enter an even integer:", {defaultAnswer: ""})var text = result.textReturnedif (text !== "") {var num = Number(text)if (!isNumberOdd(num)) {break}}}
Rounding and Truncating a Number
The handlers in Listing 20-34 and Listing 20-35 round and truncate a numeric value, and convert it to a string. Provide a numeric value and indicate a number of decimal places.
APPLESCRIPT
on roundAndTruncateNumber(theNumber, numberOfDecimalPlaces)if numberOfDecimalPlaces is 0 thenset theNumber to theNumber + 0.5return convertNumberToString(theNumber div 1)end ifset theRoundingValue to "5"repeat numberOfDecimalPlaces timesset theRoundingValue to "0" & theRoundingValueend repeatset theRoundingValue to ("." & theRoundingValue) as numberset theNumber to theNumber + theRoundingValueset theModValue to "1"repeat numberOfDecimalPlaces - 1 timesset theModValue to "0" & theModValueend repeatset theModValue to ("." & theModValue) as numberset theSecondPart to (theNumber mod 1) div theModValueif length of (theSecondPart as text) is less than numberOfDecimalPlaces thenrepeat numberOfDecimalPlaces - (the length of (theSecondPart as text)) timesset theSecondPart to ("0" & theSecondPart) as stringend repeatend ifset theFirstPart to theNumber div 1set theFirstPart to convertNumberToString(theFirstPart)set theNumber to (theFirstPart & "." & theSecondPart)return theNumberend roundAndTruncateNumber
JAVASCRIPT
function roundAndTruncateNumber(num, numDecimalPlaces) {if (numDecimalPlaces === 0) {num = num + 0.5return convertNumberToString(num / 1)}var roundingValue = "5"for (var i = 0; i < numDecimalPlaces; i++) {roundingValue = "0" + roundingValue}roundingValue = Number("0." + roundingValue)num += roundingValuevar modValue = "1"for (var i = 0; i < numDecimalPlaces - 1; i++) {modValue = "0" + modValue}modValue = Number("0." + modValue)var secondPart = Math.floor((num % 1) / modValue)var secondPartStringLength = secondPart.toString().lengthif (secondPartStringLength < numDecimalPlaces) {var count = numDecimalPlaces - secondPartStringLengthfor (var i = 0; i < count; i++) {secondPart = "0" + secondPart}}var firstPart = Math.floor(num)firstPart = convertNumberToString(firstPart)return `${firstPart}.${secondPart}`}
Listing 20-36 shows how to call the handler in Listing 20-34.
APPLESCRIPT
roundAndTruncateNumber(1.04575, 3)--> Result: "1.046"
Copyright © 2018 Apple Inc. All rights reserved. Terms of Use | Privacy Policy | Updated: 2016-06-13
