commas and rounding up numbers

This:

tell application “Finder”

	try
		set theKind to kind of alias theFile
	on error
		set theKind to "unknown file type"
	end try
	if theKind is equal to "folder" then
		repeat 
			set theSize to size of folder theFile
			if theSize is not equal to missing value then exit repeat
		end repeat
	else
		set theSize to size of alias theFile
	end if	
end tell

tell window 1
	
	set contents of text field "size" of box "box1" to (theSize as number) & "bytes" & ((theSize as number) / 1000000) & "MB"
end tell

currently this returns this: (23334411, bytes, 23.334411, MB) in the text field

I would like it to return: 23,334,411 bytes (23.34 MB)

I can’t seem to figure it out :frowning:

any suggestions?
thanks

First off, this should probably be in the AS Studio forum since I think you are talking about an AS Studio app. regardless, however, there’s probably a better way of doing this but this should work:

Jon

thanks Jon
aplogies, I was in the AS forum when I posted, don’t know quite what happened there

the subroutine works for the rounding up but on my setup is returning results like:

1.05906176E+8 bytes (105.91 MB)

I think it has something to do with calling a string value? dunno, I’m working on it.
anyway, thanks for your help, I apreciate it
Peter

Let me add my two francs worth.
I believe that 1 Megabyte=2^20 Bytes
That is there are 1,048,576 Bytes to a Megabyte.
If I am correct then the line for size converting should be


set the_string to ((my add_commas(theSize)) & " bytes (" & ((round of (theSize / 10485.76) rounding up) / 100) & " MB)") as string 

:?:

on commafy(n) -- by Barry Wainwright, adapted by NG
  if n < 1000 then return n as text
  commafy(n div 1000) & "," & text 2 thru 4 of ((1000 + n mod 1000) as string)
end commafy

on intToStr(n) -- adapted from commafy by NG
  if n < 100000000 then return n as text
  inToStr(n div 100000000) & text 2 thru 9 of ((100000000 + n mod 100000000) as string)
end intToStr

(* Round up to nearest multiple of q *)
on quantiseUp(n, q) -- from aRounderRound by Nigel Garvey
  if q < 0 then set q to -q
  tell n div q * q
    if it < n then return it + q
    it
  end tell
end quantiseUp

set theSize to 1.05906176E+8
set megabytes to quantiseUp(theSize / 1000000, 0.01)
set MBstring to intToStr(megabytes div 1)
if megabytes mod 1 is not 0 then set MBstring to MBstring & text 2 thru -1 of ((megabytes mod 1) as string)

set theString to commafy(theSize) & " bytes (" & MBstring & " MB)"
--> "105,906,176 bytes (105.91 MB)"

There are some floating-point numbers (eg. 8483.36) that don’t display accurately by conventional means, but this should cover most cases.

thanks Nigel, lworks in script editor with the “set theSize to 1.05906176E+8” example but in Xcode I get “expected end of line but found a number” error in the following places:
on commafy(n) – by Barry Wainwright, adapted by NG
if n < 1000 then return n as text
commafy(n div 1000) & “,” & text 2 thru 4 of ((1000 + n mod 1000) as string)-- stops the build process
end commafy

on intToStr(n) – adapted from commafy by NG
if n < 100000000 then return n as text
inToStr(n div 100000000) & text 2 thru 9 of ((100000000 + n mod 100000000) as string) – stops the build process
end intToStr

I’m probably doing something uuuuuh… dumb
Peter
PS I’m running Panther Dev Preview (1st version)

Hi Nigel and all :slight_smile:

on intToStr(n) -- adapted from commafy by NG
  if n < 100000000 then return n as text
  inToStr(n div 100000000) & text 2 thru 9 of ((100000000 + n mod 100000000) as string)
end intToStr

Sorry, but I believe that there is a very small error, the name of the sub routine, for the recursivity, is not exact, it should be “intToStr” instead of “inToStr” (he misses “t” after “in”)…

:wink:

yeah, well spotted Fredo
unfortunatly it doesn’t fix the problem :frowning:
any more thoughts?
thanks
Peter

OK, and, perhaps while trying to put the word “my” in front of each call of sub routine?
For exemple:

set megabytes to my quantiseUp(theSize / 1000000, 0.01) 

And also in the sub routines (for recursivity), for exemple:

on intToStr(n) -- adapted from commafy by NG 
  if n < 100000000 then return n as text 
  my intToStr(n div 100000000) & text 2 thru 9 of ((100000000 + n mod 100000000) as string) 
end intToStr

… perhaps… I hope :wink:

I have tried that and no joy I’m afraid

I keep getting “expected end of line but found a number” in the same places as before:

 on commafy(n) -- by Barry Wainwright, adapted by NG  
         if n < 1000 then return n as text 
         commafy(n div 1000) & "," & text 2 thru 4 of ((1000 + n mod 1000) as string)-- stops the build process 
 end commafy 
  
 on intToStr(n) -- adapted from commafy by NG  
         if n < 100000000 then return n as text 
         intToStr(n div 100000000) & text 2 thru 9 of ((100000000 + n mod 100000000) as string) -- stops the build process 
 end intToStr 
  

the script works great in script editor but not in my project
…?
should I be declaring any of the suroutines variables as properties in my script?
Peter

Small idea :idea:
Instead of “text 2 thru 4”, perhaps this “characters 2 thru 4”:

on commafy(n) -- by Barry Wainwright, adapted by NG  
  if n < 1000 then return n as text 
  commafy(n div 1000) & "," & characters 2 thru 4 of ("" & (1000 + (n mod 1000)))
end commafy 

… perhaps… 8)

Hi, Peter and Fredo.

Fredo. Thanks for spotting the typo in intToString. It was 3am here by the time I was ready to post so I was way past my best. :slight_smile:

Peter. I’m not sure why those handlers are giving you trouble only in your project environment, but they do contain a weakness that might be the problem. I didn’t ensure that the amounts being coerced to string were in fact integers, so an additional ‘div 1’ apiece would be in order:

on commafy(n)
  if n < 1000 then return n as text
  commafy(n div 1000) & "," & text -3 thru -1 of ((1000 + n mod 1000 div 1) as string)
end commafy

on intToStr(n) -- adapted from commafy by NG
  if n < 100000000 then return n as text
  intToStr(n div 100000000) & text 2 thru 9 of ((100000000 + n mod 100000000 div 1) as string)
end intToStr

Apart from that, both handlers are simplified to expect positive, whole numbers.

I’m still not happy about the fact that if you had something like 8483.36 megabytes, the code I posted would display it as 8483.360000000001 MB. My numToStr handler in ScriptBuilders could cope with it, but that’s a bit huge for your purposes. I’ve incorporated one of numToStr’s tricks below, which seems to do the trick. It’ll only fail if you have an unreasonably high number of megabytes on your volumes. :wink:

on commafy(n) -- by Barry Wainwright, adapted by NG
  if n < 1000 then return n as text
  commafy(n div 1000) & "," & text 2 thru 4 of ((1000 + n mod 1000 div 1) as string)
end commafy

on intToStr(n) -- adapted from commafy by NG
  if n < 100000000 then return n as text
  inToStr(n div 100000000) & text 2 thru 9 of ((100000000 + n mod 100000000 div 1) as string)
end intToStr

(* Round up to nearest multiple of q *)
on quantiseUp(n, q) -- from aRounderRound by Nigel Garvey
  if q < 0 then set q to -q
  tell n div q * q
    if it < n then return it + q
    it
  end tell
end quantiseUp

set theSize to 8.48336E+9
set megabytes to quantiseUp(theSize / 1000000, 0.01)
set MBstring to intToStr(megabytes div 1)

if (megabytes as string) contains "E" then
  set MBstring to intToStr(megabytes div 1)
  set fractionalPart to megabytes mod 1
else
-- If the megabytes value is not in scientific notation shift it 10 decimal
-- places to the left. Some numbers in the "non-scientific" range are
-- problematic and don't display properly. This shifts them out of that range.
-- Use compensatory arithmetic to get the final results.
  set megabytes to megabytes * 1.0E+10
  set MBstring to intToStr(megabytes div 1.0E+10)
  set fractionalPart to megabytes mod 1.0E+10 / 1.0E+10
end if

if fractionalPart is not 0 then set MBstring to MBstring & text 2 thru -1 of (fractionalPart as string)

set theString to commafy(theSize) & " bytes (" & MBstring & " MB)"
--> "8,483,360,000 bytes (8483.36 MB)"

OK, this works for me:

on commafy(n) -- by Barry Wainwright, adapted by NG 
	
	if n < 1000 then
		return n as text
	end if
	my commafy(n div 1000) & "," & characters 2 thru 4 of ((1000 + n mod 1000) as string)
	
end commafy

on intToStr(n) -- adapted from commafy by NG 
	if n < 100000000 then
		return n as text
	end if
	(n div 100000000) & characters 2 thru 9 of ((100000000 + n mod 100000000) as string)
	
end intToStr

(* Round up to nearest multiple of q *)
on quantiseUp(n, q) -- from aRounderRound by Nigel Garvey 
	if q < 0 then set q to -q
	tell n div q * q
		if it < n then return it + q
		it
	end tell
end quantiseUp

set megabytes to my quantiseUp(theSize / 1048576, 0.01)
	set MBstring to my intToStr(megabytes div 1)
	if megabytes mod 1 is not 0 then
		set MBstring to MBstring & characters 2 thru -1 of ((megabytes mod 1) as string)
	end if
	set theString to my commafy(theSize) & " bytes (" & MBstring & " MB)"
	tell window 1
		set contents of text field "size" of box "box1" to theString
                 end tell

most of the MB values are fairly consistant with the finders, but not all.
thanks for all your help! :slight_smile:

Peter

Nigel I’m sorry I didn’t see your latest post before my posting
looks interesting, I’ll take a look after supper
Thanks!
Peter
:o

To Jon, Nigel, Fredo and all
Thank you all for helping me
I seem to have it working ok now
main problems other than those you pointed out, being not closing the if statements
Xcode for good reasons doesn’t like that
all the best

Peter