What is the best way to generate random numbers using Objective-C on iOS?
If I use (int)((double) rand() / ((double)(RAND_MAX) + (double) 1) * 5.0) to generate a number from 0 to 4, every time I start the program on the iPhone it generates the same numbers to start off with.
There is a very similar question here on StackOverFlow. Here is one of the better solutions (no need for seeding):
int r = arc4random() % 5;
i use
#define RANDOM_SEED() srandom(time(NULL))
#define RANDOM_INT(__MIN__, __MAX__) ((__MIN__) + random() % ((__MAX__+1) - (__MIN__)))
so you can give a min and max
You should seed the random number generator with the current time.
srand(time(0));
How random do you need? If you want random enough for crypto, then use SecRandomCopyBytes().
Call srand() at the start of your program, it'll reseed random number generator
Simple function for random number generation:
int r = arc4random() % 42; // generate number up to 42 (limit)
Related
I am working on programming a Markov chain in Lua, and one element of this requires me to uniformly generate random numbers. Here is a simplified example to illustrate my question:
example = function(x)
local r = math.random(1,10)
print(r)
return x[r]
end
exampleArray = {"a","b","c","d","e","f","g","h","i","j"}
print(example(exampleArray))
My issue is that when I re-run this program multiple times (mash F5) the exact same random number is generated resulting in the example function selecting the exact same array element. However, if I include many calls to the example function within the single program by repeating the print line at the end many times I get suitable random results.
This is not my intention as a proper Markov pseudo-random text generator should be able to run the same program with the same inputs multiple times and output different pseudo-random text every time. I have tried resetting the seed using math.randomseed(os.time()) and this makes it so the random number distribution is no longer uniform. My goal is to be able to re-run the above program and receive a randomly selected number every time.
You need to run math.randomseed() once before using math.random(), like this:
math.randomseed(os.time())
From your comment that you saw the first number is still the same. This is caused by the implementation of random generator in some platforms.
The solution is to pop some random numbers before using them for real:
math.randomseed(os.time())
math.random(); math.random(); math.random()
Note that the standard C library random() is usually not so uniformly random, a better solution is to use a better random generator if your platform provides one.
Reference: Lua Math Library
Standard C random numbers generator used in Lua isn't guananteed to be good for simulation. The words "Markov chain" suggest that you may need a better one. Here's a generator widely used for Monte-Carlo calculations:
local A1, A2 = 727595, 798405 -- 5^17=D20*A1+A2
local D20, D40 = 1048576, 1099511627776 -- 2^20, 2^40
local X1, X2 = 0, 1
function rand()
local U = X2*A2
local V = (X1*A2 + X2*A1) % D20
V = (V*D20 + U) % D40
X1 = math.floor(V/D20)
X2 = V - X1*D20
return V/D40
end
It generates a number between 0 and 1, so r = math.floor(rand()*10) + 1 would go into your example.
(That's multiplicative random number generator with period 2^38, multiplier 5^17 and modulo 2^40, original Pascal code by http://osmf.sscc.ru/~smp/)
math.randomseed(os.clock()*100000000000)
for i=1,3 do
math.random(10000, 65000)
end
Always results in new random numbers. Changing the seed value will ensure randomness. Don't follow os.time() because it is the epoch time and changes after one second but os.clock() won't have the same value at any close instance.
There's the Luaossl library solution: (https://github.com/wahern/luaossl)
local rand = require "openssl.rand"
local randominteger
if rand.ready() then -- rand has been properly seeded
-- Returns a cryptographically strong uniform random integer in the interval [0, n−1].
randominteger = rand.uniform(99) + 1 -- randomizes an integer from range 1 to 100
end
http://25thandclement.com/~william/projects/luaossl.pdf
Given any number of the sort 78.689 or 1.12 for instance, what I'm looking for is to programmatically round the number to the nearest tenth place after the decimal.
I'm trying to do this in an environment where there is a math.floor() function that rounds to the lowest whole number, and as far as I can tell from documentation there's nothing like PHP's round() function.
There's simple snippet at: http://lua-users.org/wiki/SimpleRound
function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
It will misbehave when numDecimalPlaces is negative, but there's more examples on that page.
You can use coercion to do this...
It work just like printf... You can try to do something like in this snippet.
value = 8.9756354
print(string.format("%2.1f", value))
-- output: 9.0
Considering that this is roblox, it would just be easier to make this a global variable instead of making a single module or creating your own gloo.
_G.round = function(x, factor)
local factor = (factor) and (10 ^ factor) or 0
return math.floor((x + 0.5) * factor) / factor
end
In my case, I was simply trying to make a string representation of this number... however, I imagine this solution could prove useful to others as well.
string.sub(tostring(percent * 100), 1, 4)
so to bring it back to a numerical representation, you could simply call tonumber() on the resulting number.
In an objective C script I am trying to get a random string from an NSArray by using
int idx = rand() % self.adviceList.count;
However, every time it executes it throws an EXC_ARITHMETIC error. My question is twofold:
1) How do I get the code to run
2) is there a more portable way to generate a random int/NSUInteger in iOS programming?
The code you posted should work. Probably self.adviceList.count returns zero and this is a reason of EXC_ARITHMETIC.
As Mattt Thompson wrote in his article:
Use arc4random() and its related functions.
Specifically, to generate a random number between 0 and N - 1, use
arc4random_uniform(), which avoids modulo bias.
Try using arc4random_uniform( num ) which takes in an unsigned int
rand() returns an int and random() returns a long so it is possible modulus doesn't like unsigned numbers?
i used arc4random to create a random number, is there a way to tell arc4random to begin at for example -5 instead of 0? because i want to create a random number in the range of
-3,4 to 4,3, im not that good in iOS developing yet, so what other possiblities do i have if that wont work with arc4random (Links are appreciated if theres a guide or something like that)
First of all, use arc4random_uniform to get a random number in the desired absolute range (for -3 to 4 it would be 7): arc4random_uniform(7).
You might also see the form arc4random() % max, but that will introduce a modulo bias making the distribution less random, arc4random_uniform is prefered.
Afterwards, adjust your lower bound:
arc4random_uniform(7) - 3
apple docs
Since arc4random() % n returns an integer from 0..n-1, arc4random() % (n - k) + k returns one from k..n-1. Plug in k=-5. Is that what you need?
If you want it to start at -5 instead of 0, just subtract 5.
If you want to create a random number in the range of -3 to 4, just create a number from 0 to 7 and subtract 3 from it.
The arc4random function gives you a number from zero to 4,294,967,295. To change that to a number from 0 to 7, just divide by 613,566,756. (Or use arc4random_uniform to avoid any bias.)
Even though Lua does not differentiate between floating point numbers and integers, there are some cases when you want to use integers. What is the best way to covert a number to an integer if you cannot do a C-like cast or without something like Python's int?
For example when calculating an index for an array in
idx = position / width
how can you ensure idx is a valid array index? I have come up with a solution that uses string.find, but maybe there is a method that uses arithmetic that would obviously be much faster. My solution:
function toint(n)
local s = tostring(n)
local i, j = s:find('%.')
if i then
return tonumber(s:sub(1, i-1))
else
return n
end
end
You could use math.floor(x)
From the Lua Reference Manual:
Returns the largest integer smaller than or equal to x.
Lua 5.3 introduced a new operator, called floor division and denoted by //
Example below:
Lua 5.3.1 Copyright (C) 1994-2015 Lua.org, PUC-Rio
>12//5
2
More info can be found in the lua manual
#Hofstad is correct with the math.floor(Number x) suggestion to eliminate the bits right of the decimal, you might want to round instead. There is no math.round, but it is as simple as math.floor(x + 0.5). The reason you want to round is because floats are usually approximate. For example, 1 could be 0.999999996
12.4 + 0.5 = 12.9, floored 12
12.5 + 0.5 = 13, floored 13
12.6 + 0.5 = 13.1, floored 13
local round = function(a, prec)
return math.floor(a + 0.5*prec) -- where prec is 10^n, starting at 0
end
why not just use math.floor()? it would make the indices valid so long as the numerator and denominator are non-negative and in valid ranges.