How can I generate a large random number that is an integer, and not a real?

When executing this

set a to random number from (7.0E+8 as integer) to (7.6E+8 as integer)

I get something like (literally) 7.48262040226155E+8 in return.

I actually entered the line like this:

set a to random number from (700000000 as integer) to (760000000 as integer)

but when I compile it, the format changes to “scientific”, which seems to cause the result to be a real rather than an integer.

I have tried different versions along these line, using round, text and string, to no avail:

set a to (round (random number from (7.0E+8 as integer) to (7.6E+8 as integer))) as string

Ultimately I want a text/string in the format 0701234567, so something like:

set a to "0" & (random number from (7.0E+8 as integer) to (7.6E+8 as integer) as string)

but this specific code generates results like 04,493136217897×10^+8 - WTF!?!? Is shoud be between 70 and 76 millions but this isn’t even close.

I have read Commands Reference but it doesn’t help a lot.

I googled ‘applescript suppress exponential notation’. This came up.

Are you referring to the suggestion to use as centimeters? I have tried that too, but didn’t include it in my original post.

set a to (random number from (7.0E+8) to (7.6E+8) as centimeters)

returns

7.59229569014948E+8

Both scientific notation and too many decimals.

No. Somewhere in there is a handler to convert a number in exponential notation to a string. There’s no way you can get around this. If you want to loose the exponential notation you have to display numbers as strings.

As I wrote in the OP I am gonna use it as a string in the end so a string is perfectly fine. I just want a random string that starts with 0 folloed by a number between 70 and 76 millions.

    --Running under AppleScript 2.8, MacOS 13.4.1
    set a to random number from (7.0E+8 as integer) to (7.6E+8 as integer)
    "0" & number_to_text(a)-->0749045798
    --I think those should both be ...E+7
    

    on number_to_text(this_number)
        set this_number to this_number as text
        if this_number contains "E+" then
            set x to the offset of "." in this_number
            set y to the offset of "+" in this_number
            set z to the offset of "E" in this_number
            set the decimal_adjust to characters (y - (length of this_number)) thru -1 of this_number as string as number
            if x is not 0 then
                set the first_part to characters 1 thru (x - 1) of this_number as string
            else
                set the first_part to ""
            end if
            set the second_part to characters (x + 1) thru (z - 1) of this_number as string
            set the converted_number to the first_part
            repeat with i from 1 to the decimal_adjust
                try
                    set the converted_number to the converted_number & character i of the second_part
                on error
                    set the converted_number to the converted_number & "0"
                end try
            end repeat
            return the converted_number
        else
            return this_number
        end if
    end number_to_text
1 Like

This is weird

on run {}
	set s to "0"
	set b to random number from 0 to 6
	set s to s & (b as string)
	log s
end run

(*s: 03*)

but

on run {}
	set s to "0"
	set b to (random number from 0 to 6 as string)
	set s to s & b
	log s
end run

(*s: 00,496302375332*)

???

Why so complicated?

This one works

on run {}
	set s to "07"
	set s to s & ((random number from 0 to 6) as string)
	repeat 7 times
		set s to s & ((random number from 0 to 9) as string)
	end repeat
	return s
end run

Existing, general purpose handler.

I don’t understand why this works or even if it works correctly, so I offer this with a big FWIW:

set a to ((random number from 7.0E+8 to 7.6E+8) as centimeters) as text
set aRandomNumber to "0" & text 1 thru ((the offset of "." in a) - 1) of a
1 Like

The OP’s question has been answered (more or less), and I thought I would post an ASObjC solution just in case one is needed by a forum member in the future. With the Foundation framework in memory, the timing result is less than a millisecond:

use framework "Foundation"
use scripting additions

set aRandomNumber to random number from 7.0E+8 to 7.6E+8
set theFormatter to current application's NSNumberFormatter's new()
theFormatter's setNumberStyle:(current application's NSNumberFormatterNoStyle)
set aRandomNumber to "0" & ((theFormatter's stringFromNumber:aRandomNumber) as text)

If the random number needs to be formatted in some particular manner, another alternative is:

use framework "Foundation"
use scripting additions

set aRandomNumber to random number from 7.0E+8 to 7.6E+8
set theFormatter to current application's NSNumberFormatter's new()
theFormatter's setFormat:"#,##0" -- user set as desired
set aRandomNumber to (theFormatter's stringFromNumber:aRandomNumber) as text

You are actually trying to get numbers in excess of 700 million, not 70. This exceeds the applescript limit for an integer.

Discussion

The biggest value (positive or negative) that can be expressed as an integer in AppleScript is ±536870911, which is equal to ±(2^29 – 1). Larger integers are converted to real numbers, expressed in exponential notation, when scripts are compiled.

2 Likes

If the desired output is always a ‘07’ followed by eight digits between 0 and 60000000, then create an 8-digit random number and append it to ‘07’

set a to "07" & a

Your number will never exceed the limit.

Here is one way to do it:

set xy to (random number) * 60000000 as integer as text
set l to length of xy
log l
set c to 0

if l is less than 8 then
	repeat (8 - l) times
		
		set xy to "0" & xy
		set c to c + 1
		log c
	end repeat
end if

set yz to "07" & xy

Note that if the generated random number is relatively small, ie < 10M, you will need to pad it with zeroes.

I added a loop for when the length of the random number is < 8. The loop will run once for each missing digit and prepend a “0”. For example, if the random number was 5, then it would run seven times and add seven “0” to end up with “000000005”. Once out of the loop, the result is appended to the “07” for the final string.

The log commands are optional but they let you see what is happening in the log history. In this example, the random number was ‘9814603’ which, at seven digits, is one short, so it will be padded with one “0”

tell current application
	random number
		--> 0.163576708404
	(*7*)
	(*1*)
end tell
Result:
"0709814603"
2 Likes

The following is a different implementation of Mockman’s suggestion.

set xy to random number from 0 to 60000000
set xy to "07" & text -8 thru -1 of (("0000000") & xy)
1 Like

That’s pretty clever.

I was also thinking of just concatenating eight, random, one-digit numbers together:

set rLen to 8 -- desired number of digits
set len to ""
repeat rLen times
	set len to len & my dom()
end repeat
set finStr to "07" & len
--> "0739280210"

on dom()
	set x to random number from 0 to 9
	return x
end dom

What is happening is that it generated a random number of 0.496302375332 and then appended that to “0”.

Note that I have a . (point or period) as my decimal separator but it looks like you have a , (comma) as yours.

"0" & "0,496302375332"
--> 00,496302375332

I don’t understand, can you elaborate?

How does this work? I think I can guess but I don’t understand the mechanism.

That is exactly what I did in my solution above.

But why does adding as string make it behave differently? Yes, I use comma for decimals.