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.
Related
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
Why does my method return values < 0.4 in some cases?
e.g. 0.225501
#define ARC4RANDOM_MAX 0x100000000
float myVar = [self randomFloat:0.4 to:2];
- (float)randomFloat:(int)from to:(int)to
{
return ((double)arc4random() / ARC4RANDOM_MAX) * (to - from) + from;
}
You are casting your parameters to integers (which in your case changes your range to between 0 and 2), change the parameters to be float.
- (float)randomFloat:(float)from to:(float)to
when dividing and using floats the precision of the decimals is sometimes lost. Maybe you can use a long with N fixed number of digits and place the decimal point before those digits. The other day I was getting strange results when adding (1 + (3/10))= should be 1.3 but I always had something like 1.29995 . Hope it helps
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.
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.
Let's say i have this bit field value: 10101001
How would i test if any other value differs in any n bits. Without considering
the positions?
Example:
10101001
10101011 --> 1 bit different
10101001
10111001 --> 1 bit different
10101001
01101001 --> 2 bits different
10101001
00101011 --> 2 bits different
I need to make a lot of this comparisons so i'm primarily looking for perfomance but any
hint is very welcome.
Take the XOR of the two fields and do a population count of the result.
if you XOR the 2 values together, you are left only with the bits that are different.
You then only need to count the bits which are still 1 and you have your answer
in c:
unsigned char val1=12;
unsigned char val2=123;
unsigned char xored = val1 ^ val2;
int i;
int numBits=0;
for(i=0; i<8; i++)
{
if(xored&1) numBits++;
xored>>=1;
}
although there are probably faster ways to count the bits in a byte
(you could for instance use a lookuptable for 256 values)
Just like everybody else said, use XOR to determine what's different and then use one of these algorithms to count.
This gets the bit difference between the values and counts the bits three at a time:
public static int BitDifference(int a, int b) {
int cnt = 0, bits = a ^ b;
while (bits != 0) {
cnt += (0xE994 >> ((bits & 7) << 1)) & 3;
bits >>= 3;
}
return cnt;
}
XOR the numbers, then the problem becomes a matter of counting the 1s in the result.
In Java:
Integer.bitCount(a ^ b)
Comparison is performed with XOR, as others already answered.
counting can be performed in several ways:
shift left and addition.
lookup in a table.
logic formulas that you can find with Karnaugh maps.