arc4random() gives negative Number in iOS - ios

Sometime arc4random() gives negative number also in objective C.
My code is as follow:
Try 1:
long ii = arc4random();
Try 2:
int i = arc4random();
How can I only get positivite random number?
Thank you,

No, it's always positive as it returns an unsigned 32-bit integer (manpage):
u_int32_t arc4random(void);
You are treating it as a signed integer, which is incorrect.

You should use the arc4random_uniform() function. this is the most common random function used.
arc4random_uniform() function
Returns a random number between 0 and the inserted parameter minus 1.
For example arc4random_uniform(3) may return 0, 1 or 2 but not 3.
Example
u_int32_t randomPositiveNo = arc4random_uniform(5) + 1; //to get the range 1 - 5

Related

Evaluation (NSIntegers) inside if-statement Objective-C

I am in doubt, why this work correctly:
NSInteger row = indexPath.row;
NSInteger preloadTrigger = self.nodes.count - 20;
if (row >= preloadTrigger) {
[self.loader loadNextposts];
}
And this does not (just skips the if-statement):
if (indexPath.row >= self.nodes.count - 20) {
[self.loader loadNextposts];
}
when the value of self.nodes.count - 20 is negative.
However, when the value of the expression is positive, it works fine always.
A very strange behavior, as I cannot see semantic difference in two expressions.
Update:
So, I decided to test it:
(lldb) po self.nodes.count - 20
18446744073709551601
(lldb) po preloadTrigger
-15
According to Apple Docs, count property is a NSUIntegerin objective-C.
When you write :
NSInteger preloadTrigger = self.nodes.count - 20;
In fact you are casting count to a NSInteger object, and can have a negative value if count isn't greater than 20.
But when you write :
(indexPath.row >= self.nodes.count - 20)
count is a NSUInteger object, and subtract 20 from it will always lead to a positive number (a huge one by the way).
Because nodes.count is NSUInteger and row is NSInteger. Unsigned integer - 20 is never a negative value, but results a huge positive value where you expect it to be negative.
I'll add some explanation to the other, correct answers.
So, here is how it goes:
self.nodes.count is of type NSUInteger, which is the same as unsigned long int in 64 bit systems, or alternatively unsigned int in 32 bit systems.
The literal 20 is of type int.
When you form the expression self.nodes.count - 20, 20 is 'promoted' to the unsigned integer type of the other operand (self.nodes.count), because it has the wider range of the two.
That is because, when both operands have types of different sizes, the smaller one gets promoted to the larger one to make them equal and calculate the result in those terms (in hardware, arithmetical operations between values of different types aren't really defined - the bit representations differ).
The problem is that, in exchange for being able to represent a wider range of positive values with the same bit length, unsigned integers can not represent negative values. So, when 20 is greater than self.nodes.count, the result "wraps around" to a large, unsigned integer.
On the other hand indexPath.row, too, is an unsigned integer (NSUInteger), so you end up comparing the relatively small row value with the huge result of the subtraction operation; the test:
if (indexPath.row >= self.nodes.count - 20)
...always fails (the left side is smaller).
If you first cast both results to signed integer and then compare those signed integers:
NSInteger row = indexPath.row;
NSInteger preloadTrigger = self.nodes.count - 20;
if (row >= preloadTrigger) {
...then no wrapping/underflow occurs and you get the expected result.

Integer overflow in Fibonacci number

I was solving this codechef problem on Fibonacci numbers. It says number is of 1000 digits then why it is not causing integer overflow in tester's solution when it is scanning the array and storing it in unsigned long long int. I can't understand how solution is working. Below is the problem and tester's solution.
The Head Chef has been playing with Fibonacci numbers for long . He has learnt several tricks related to Fibonacci numbers . Now he wants to test his chefs in the skills .
A fibonacci number is defined by the recurrence :
f(n) = f(n-1) + f(n-2) for n > 2
and f(1) = 0
and f(2) = 1 .
Given a number A , determine if it is a fibonacci number.
Input
The first line of the input contains an integer T denoting the number of test cases. The description of T test cases follows.
The only line of each test case contains a single integer A denoting the number to be checked .
Output
For each test case, output a single line containing "YES" if the given number is a fibonacci number , otherwise output a single line containing "NO" .
Constraints
1 ≤ T ≤ 1000
1 ≤ number of digits in A ≤ 1000
The sum of number of digits in A in all test cases <= 10000.
Example
Input:
3
3
4
5
Output:
YES
NO
YES
**Tester's solution:**
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
#include <cstring>
using namespace std;
int const mx = 6666;
set <unsigned long long> f;
unsigned long long fib[mx + 10];
char s[mx + 1];
int main(){
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
fib[0] = 0;
fib[1] = 1;
f.insert(1);
f.insert(0);
int i;
for (i = 2; i <= mx; i++){
fib[i] = fib[i - 1] + fib[i - 2];
f.insert(fib[i]);
}
int tc;
cin>>tc;
while (tc--){
unsigned long long n = 0, ten = 10;
cin>>s;
int len = strlen(s);
for (i = 0; i < len; i++){
char q = s[i];
unsigned long long a = q - '0';
n = n * ten + a;
}
if (f.find(n) == f.end()) printf("NO\n");
else printf("YES\n");
}
return 0;
}
From cplusplus you will see that,
ULLONG_MAX Maximum value for an object of type unsigned long long int is 18446744073709551615 (264-1) or greater.
The actual value depends on the particular system and library implementation, but shall reflect the limits of these types in
the target platform.
Above information is just to let you know its a BIG number. Moreover the cause of not getting overflow is not the limit i mentioned.
Most probably, the input file of judge does not contain any input that can cause an overflow.
And its still possible to set such input even after fulfilling the conditions,
1 ≤ T ≤ 1000
1 ≤ number of digits in A ≤ 1000
The sum of number of digits in A in all test cases <= 10000.

Rounding to specific value?

I need to round a number, let's say 543 to either the hundreds or the tens place. It could be either one, as it's part of a game and this stage can ask you to do one or the other.
So for example, it could ask, "Round number to nearest tens", and if the number was 543, they would have to enter in 540.
However, I don't see a function that you can specify target place value to round at. I know there's an easy solution, I just can't think of one right now.
From what I see, the round function rounds the last decimal place?
Thanks
To rounding to 100's place
NSInteger num=543;
NSInteger deci=num%100;//43
if(deci>49){
num=num-deci+100;//543-43+100 =600
}
else{
num=num-deci;//543-43=500
}
To round to 10's place
NSInteger num=543;
NSInteger deci=num%10;//3
if(deci>4){
num=num-deci+100;//543-3+10 =550
}
else{
num=num-deci;//543-3=540
}
EDIT:
Tried to merge the above in one:
NSInteger num=543;
NSInteger place=100; //rounding factor, 10 or 100 or even more.
NSInteger condition=place/2;
NSInteger deci=num%place;//43
if(deci>=condition){
num=num-deci+place;//543-43+100 =600.
}
else{
num=num-deci;//543-43=500
}
You may just use an algorithm in your code:
For example, lets say that you need to round up a number to hundred's place.
int c = 543
int k = c % 100
if k > 50
c = (c - k) + 100
else
c = c - k
To round numbers, you can use the modulus operator, %.
The modulus operator gives you the remainder after division.
So 543 % 10 = 3, and 543 % 100 = 43.
Example:
int place = 10;
int numToRound=543;
// Remainder is 3
int remainder = numToRound%place;
if(remainder>(place/2)) {
// Called if remainder is greater than 5. In this case, it is 3, so this line won't be called.
// Subtract the remainder, and round up by 10.
numToRound=(numToRound-remainder)+place;
}
else {
// Called if remainder is less than 5. In this case, 3 < 5, so it will be called.
// Subtract the remainder, leaving 540
numToRound=(numToRound-remainder);
}
// numToRound will output as 540
NSLog(#"%i", numToRound);
Edit: My original answer was submitted before it was ready, because I accidentally hit a key to submit it. Oops.

Why is arc4random() behaving different when storing it in a variable or not?

int chance = -5;
int rand = arc4random() % 100; // Number from 0 to 99
if (rand <= chance) { // This will never happen
NSLog(#"This is... NOT POSSIBLE");
}
Effectively, this never happens. But
int chance = -5;
if (arc4random() % 100 <= chance) {
NSLog(#"This is... NOT POSSIBLE");
}
Here, instead of storing it in a variable, I placed the random number expression directly in the condition. And the condition is fulfilled (sometimes).
Why is that? How can I debug this behavior?
Type promotion rules.
arc4random returns an unsigned value. That means in your second case, the -5 gets promoted to that same unsigned type, turning it into 4294967291. 4+ billion is definitely larger than any number 0-99!
Let's walk through what happens in both of your examples.
From your first example, in this line:
int rand = arc4random() % 100;
arc4random() returns an unsigned value. So then it looks like:
int rand = someUnsignedNumber % 100;
The 100 is a signed int, so it gets promoted to the same type as someUnsignedNumber, and the % operation is applied. After that you have:
int rand = someUnsignedNumberBetween0And99;
Assigning that unsigned number to int rand makes it back into a signed number. Your comparison then goes forward as expected.
In the second example, you have this line:
if (arc4random() % 100 <= chance)
The same things happen with arc4random() % 100, yielding something like:
if (someUnsignedNumberBetween0And99 <= chance)
But here, chance is a signed number. It gets promoted, changing its value as described above, and you end up with the strange behaviour you're seeing.
Silly, silly type system of C... If you read the man page for arc4random(), you find out that its prototype is
u_int32_t arc4random(void);
So it returns an unsigned integer.
When comparing its - unsigned - result with another integer, the unsignedness "wins": the other value (-5) is promoted to the unsigned type (u_int32_t in this case), it rolls over (since unsigned integer "underflow" is designed to work like this in C - you'll get 2 ^ 32 - 5) and so an "erroneous" (i. e. behaving-as-unexpected) comparison occurs.
When you explicitly assign the value to an int (i. e. signed) variable, this promotion does not occur since the comparison is between two signed types, so it is evaluated as you would expect.

How to select range of values when using arc4random()

Can I set a range of numbers when using arc4random()? For example 50-100 only.
As pointed out in other posts below, it is better to use arc4random_uniform. (When this answer was originally written, arc4random_uniform was not available). Besides avoiding the modulo bias of arc4random() % x, it also avoids a seeding problem with arc4random when used recursively in short timeframes.
arc4random_uniform(4)
will generate 0, 1, 2 or 3. Thus you could use:
arc4random_uniform(51)
and merely add 50 to the result to get a range between 50 & 100 (inclusive).
To expand upon JohnK comment.
It is suggested that you use the following function to return a ranged random number:
arc4random_uniform(51)
which will return a random number in the range 0 to 50.
Then you can add your lower bounds to this like:
arc4random_uniform(51) + 50
which will return a random number in the range 50 to 100.
The reason we use arc4random_uniform(51) over arc4random() % 51 is to avoid the modulo bias. This is highlighted in the man page as follows:
arc4random_uniform(upper_bound) will return a uniformly distributed random number less than upper_bound. arc4random_uniform() is recommended over constructions like ``arc4random() % upper_bound'' as it avoids "modulo bias" when the upper bound is not a power of two.
In short you get a more evenly distributed random number generated.
int fromNumber = 10;
int toNumber = 30;
int randomNumber = (arc4random()%(toNumber-fromNumber))+fromNumber;
Will generate randon number between 10 and 30, i.e. 11,12,13,14......29
You can use this code for generating random values with range:
//range from 50 to 100
int num1 = (arc4random() % 50) + 50; or
int num1 = arc4random_uniform(50) + 50;
//range from 0-100
int num1 = arc4random() % 100; or
int num1 = arc4random_uniform(100);
In Swift you can use this (inspired by answer of #Justyn)
func generateRandomKey(fromRange rangeFrom:Int, toRange rangeTo:Int) -> Int{
let theKey = arc4random_uniform(UInt32(rangeTo - rangeFrom)) + UInt32(rangeFrom)
return Int(theKey)
}
Will always give you a random range Integer.
In many situations 10 thru 30 would mean inclusive, (includes 10 and 30) ...
int fromNumber = 10;
int toNumber = 30;
toNumber ++;
int randomNumber = (arc4random()%(toNumber-fromNumber))+fromNumber;
Notice the difference toNumber - fromNumber is now 21 ... (20+1) which yields the possible results of 0 thru 20 (inclusive) which when added to fromNumber (10) results in 10 thru 30 (inclusive).

Resources