I have a script calculating aspect ratios which finally is something like decimals to fraction and ‘optimizing fractions’.
Seems to work, but there is an oddity when converting decimals with repeating fraction digits
set theNumber2 to (tmpVal - theNumber) as string -- string otherwise the "aVal mod 1" will fail
If I don’t convert to string and then to real the following will fail
if aVal mod 1 = 0 then exit repeat
Bellow the script.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
property cA : a reference to current application
property decDiv : "."
property notDecDiv : ","
set decDiv to (text 2 of ((1 / 2) as string))
if decDiv = "." then
set notDecDiv to ","
else
set notDecDiv to "."
end if
(* === work ? === *)
--set theNumber to "1.85"
--set repParts to 0
set theNumber to "1.833"
set repParts to 2
--set theNumber to "29.970029"
--set repParts to 6
set theNumber to my replaceString(theNumber, notDecDiv, decDiv)
my getFraction(theNumber, repParts)
(* === math === *)
on getFraction(theNumber, repParts)
if repParts = 0 then
# A, standard decimal
set theNumber to theNumber as real
set exp to 0
repeat
set bVal to (10 ^ exp)
set aVal to (theNumber * bVal)
if aVal mod 1 = 0 then exit repeat
set exp to exp + 1
end repeat
else
# B, repeating numbers
set repExp to (10 ^ repParts)
set decOff to (offset of decDiv in theNumber) + 1
set decLen to length of (text decOff thru -1 of theNumber)
set decExp to (10 ^ decLen)
set repVal to (text -repParts thru -1 of theNumber)
set repVal to (repVal / decExp)
set tmpVal to ((theNumber * repExp) + repVal)
set bVal to (repExp - 1) as integer
set theNumber2 to (tmpVal - theNumber) as string -- string otherwise the "aVal mod 1" will fail
set theNumber2 to theNumber2 as real
set exp to 0
repeat
set bVal2 to (10 ^ exp)
set aVal to (theNumber2 * bVal2) as real
if aVal mod 1 = 0 then exit repeat
set exp to exp + 1
end repeat
set bVal to bVal * bVal2
log {aVal, bVal}
end if
return my getRatio({aVal, bVal})
end getFraction
on getRatio(theNumbers)
set {x, y} to theNumbers
set res to ((x / y) * 1000) as integer
set res to (res / 1000) as string
repeat
set i to gcd(x, y)
if i = 1 then exit repeat
set {x, y} to {x div i, y div i}
end repeat
set asp to {x, ":", y} as string
--set {x, y} to theNumbers
--set theNumbers to {x as integer, y as integer}
return {asp, res, theNumbers}
--return asp
end getRatio
on gcd(a, b) -- get greatest common divisor
repeat while b > 0
set {a, b} to {b, a mod b}
end repeat
return a
end gcd
(* === other === *)
on replaceString(sourceText, searchString, replacementString)
set the sourceString to cA's NSString's stringWithString:sourceText
try
return (the sourceString's stringByReplacingOccurrencesOfString:searchString withString:replacementString) as string
on error
return (the sourceString)
end try
end replaceString