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 = 12
- num.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 string
- set theOffset to offset of "E" in theNumberString
- if theOffset = 0 then return theNumberString
- set thePrefix to text 1 thru (theOffset - 1) of theNumberString
- set theConvertedNumberPrefix to ""
- if thePrefix begins with "-" then
- set theConvertedNumberPrefix to "-"
- if thePrefix = "-" then
- set thePrefix to ""
- else
- set thePrefix to text 2 thru -1 of thePrefix
- end if
- end if
- set theDecimalAdjustment to (text (theOffset + 1) thru -1 of theNumberString) as number
- set isNegativeDecimalAdjustment to theDecimalAdjustment is less than 0
- if isNegativeDecimalAdjustment then
- set thePrefix to (reverse of (characters of thePrefix)) as string
- set theDecimalAdjustment to -theDecimalAdjustment
- end if
- set theDecimalOffset to offset of "." in thePrefix
- if theDecimalOffset = 0 then
- set theFirstPart to ""
- else
- set theFirstPart to text 1 thru (theDecimalOffset - 1) of thePrefix
- end if
- set theSecondPart to text (theDecimalOffset + 1) thru -1 of thePrefix
- set theConvertedNumber to theFirstPart
- set theRepeatCount to theDecimalAdjustment
- if (length of theSecondPart) is greater than theRepeatCount then set theRepeatCount to length of theSecondPart
- repeat with a from 1 to theRepeatCount
- try
- set theConvertedNumber to theConvertedNumber & character a of theSecondPart
- on error
- set theConvertedNumber to theConvertedNumber & "0"
- end try
- if 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 string
- return theConvertedNumberPrefix & theConvertedNumber
- end 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 digits
- set theLastDigit to theNumber mod 10
- set theLastTwoDigits to theNumber mod 100
- set theSuffix to "th"
- if {1, -1} contains theLastDigit and {11, -11} does not contain theLastTwoDigits then
- set theSuffix to "st"
- else if {2, -2} contains theLastDigit and {12, -12} does not contain theLastTwoDigits then
- set theSuffix to "nd"
- else if {3, -3} contains theLastDigit and {13, -13} does not contain theLastTwoDigits then
- set theSuffix to "rd"
- end if
- -- Return the number and suffix
- return (theNumber as string) & theSuffix
- end addDescriptiveSuffixToNumber
JAVASCRIPT
- function addDescriptiveSuffixToNumber(num) {
- // Convert the number to absolute value
- var integer = Math.abs(num)
- // Determine the suffix to add, based on the last two digits
- var suffix = "th"
- var lastDigit = integer % 10
- var lastTwoDigits = integer % 100
- if (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 suffix
- return 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 10
- set theTestResults to theTestResults & addDescriptiveSuffixToNumber(a)
- if a is less than 10 then set theTestResults to theTestResults & ", "
- end repeat
- theTestResults
- --> 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 thePersonList
- repeat with a from 1 to theListLength
- set theSuffixedNumber to addDescriptiveSuffixToNumber(a)
- set thePerson to item a of thePersonList
- display dialog "The " & theSuffixedNumber & " person in list is " & thePerson & "."
- end repeat
JAVASCRIPT
- var app = Application.currentApplication()
- app.includeStandardAdditions = true
- var personList = ["Sal", "Ben", "Chris", "David"]
- var listLength = personList.length
- for (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 negative
- set isNegative to theNumber is less than 0
- -- Determine when the maximum number of digits will be reached
- set theThreshold to (10 ^ theMaxLeadingZeroCount) as integer
- -- If the number is shorter than the maximum number of digits
- if theNumber is less than theThreshold then
- -- If the number is negative, convert it to positive
- if isNegative = true then set theNumber to -theNumber
- -- Add the zeros to the number
- set theLeadingZeros to ""
- set theDigitCount to length of ((theNumber div 1) as string)
- set theCharacterCount to (theMaxLeadingZeroCount + 1) - theDigitCount
- repeat theCharacterCount times
- set theLeadingZeros to (theLeadingZeros & "0") as string
- end repeat
- -- Make the number negative, if it was previously negative
- if isNegative = true then set theLeadingZeros to "-" & theLeadingZeros
- -- Return the prefixed number
- return (theLeadingZeros & (theNumber as text)) as string
- -- If the number is greater than or equal to the maximum number of digits
- else
- -- Return the original number
- return theNumber as text
- end if
- end addLeadingZerosToNumber
JAVASCRIPT
- function addLeadingZerosToNumber(num, maxLeadingZeroCount) {
- var leadingZeros = ""
- // Convert the number to absolute value
- var absNum = Math.abs(num)
- // Determine when the maximum number of digits will be reached
- var threshold = Math.pow(10, maxLeadingZeroCount)
- // If the number is shorter than the maximum number of digits
- if (absNum < threshold) {
- // Prepare a leading zeros string
- var digitCount = Math.trunc(absNum).toString().length
- var charCount = maxLeadingZeroCount + 1 - digitCount
- for (var i = 0 ; i < charCount; i++) {
- leadingZeros += "0"
- }
- }
- // Add the zeros to the number
- var result = `${leadingZeros}${absNum}`
- // Make the number negative, if it was previously negative
- if (num < 0) {
- result = `-${result}`
- }
- // Return the prefixed number
- return 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 string
- set theNumber to convertNumberToString(theNumber)
- -- Determine the length of the number
- set theNumberLength to length of theNumber
- -- Reverse the number so a comma can be added every 3 digits
- set 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 order
- set theConvertedNumber to ""
- repeat with a from 1 to theNumberLength
- if a is theNumberLength or (a mod 3) is not 0 then
- set theConvertedNumber to (character a of theNumber & theConvertedNumber) as string
- else
- set theConvertedNumber to ("," & character a of theNumber & theConvertedNumber) as string
- end if
- end repeat
- -- Return the comma delimited number
- return theConvertedNumber
- end convertNumberToCommaDelimitedString
JAVASCRIPT
- function convertNumberToCommaDelimitedString(num) {
- // Convert the number to a string
- var numString = num.toString()
- if (numString.indexOf("e") != - 1) {
- numString = convertNumberToString(numString)
- }
- // Reverse the number so a comma can be added every 3 digits
- numString = numString.split("").reverse().join("")
- var numStringWithCommas = ""
- // Determine the length of the number
- var numStringLength = numString.length
- // Loop through the number's digits, add commas, and put the numbers back in the correct order
- for (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 number
- return 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 then
- return true
- else
- return false
- end if
- end 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
- repeat
- display dialog "Enter an even integer:" default answer ""
- try
- if text returned of result is not "" then set theNumberProvided to text returned of result as integer
- if isNumberOdd(theNumberProvided) is false then exit repeat
- end try
- end repeat
JAVASCRIPT
- var app = Application.currentApplication()
- app.includeStandardAdditions = true
- while (true) {
- var result = app.displayDialog("Enter an even integer:", {defaultAnswer: ""})
- var text = result.textReturned
- if (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 then
- set theNumber to theNumber + 0.5
- return convertNumberToString(theNumber div 1)
- end if
- set theRoundingValue to "5"
- repeat numberOfDecimalPlaces times
- set theRoundingValue to "0" & theRoundingValue
- end repeat
- set theRoundingValue to ("." & theRoundingValue) as number
- set theNumber to theNumber + theRoundingValue
- set theModValue to "1"
- repeat numberOfDecimalPlaces - 1 times
- set theModValue to "0" & theModValue
- end repeat
- set theModValue to ("." & theModValue) as number
- set theSecondPart to (theNumber mod 1) div theModValue
- if length of (theSecondPart as text) is less than numberOfDecimalPlaces then
- repeat numberOfDecimalPlaces - (the length of (theSecondPart as text)) times
- set theSecondPart to ("0" & theSecondPart) as string
- end repeat
- end if
- set theFirstPart to theNumber div 1
- set theFirstPart to convertNumberToString(theFirstPart)
- set theNumber to (theFirstPart & "." & theSecondPart)
- return theNumber
- end roundAndTruncateNumber
JAVASCRIPT
- function roundAndTruncateNumber(num, numDecimalPlaces) {
- if (numDecimalPlaces === 0) {
- num = num + 0.5
- return convertNumberToString(num / 1)
- }
- var roundingValue = "5"
- for (var i = 0; i < numDecimalPlaces; i++) {
- roundingValue = "0" + roundingValue
- }
- roundingValue = Number("0." + roundingValue)
- num += roundingValue
- var 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().length
- if (secondPartStringLength < numDecimalPlaces) {
- var count = numDecimalPlaces - secondPartStringLength
- for (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

