views:

118

answers:

3

Hi everybody:

I'm sure I'm missing something and the answer is very simple, but I can't seem to understand why this is happening. I'm trying to make an average of dates:

NSInteger runningSum =0;
NSInteger count=0;
for (EventoData *event in self.events) {
    NSDate *dateFromString = [[NSDate alloc] init];
    if (event.date != nil) {
        dateFromString = [dateFormatter dateFromString:event.date];
        runningSum += (NSInteger)[dateFromString timeIntervalSince1970];
        count += 1;
    }
}
if (count>0) {
    NSLog(@"average is: %@",[NSDate dateWithTimeIntervalSince1970:(NSInteger)((CGFloat)runningAverage/count)]);
}

Everything seems to work OK, except for runningSum += (NSInteger)[dateFromString timeIntervalSince1970], which gives an incorrect result. If I put a breakpoint when taking the average of two equal dates (2009-10-10, for example, which is a timeInterval of 1255125600), runningSum is -1784716096, instead of the expected 2510251200.

I've tried using NSNumber and I get the same result. Can anybody point me in the right direction?

Thanks!

Antonio

+2  A: 

Is there some reason you are fudging about with NSInteger?

[NSDate timeIntervalSince1970] returns an NSTimeInterval, which is basically a double. Clean up the code and see if that helps.

ivans
Doh! sorry, I feel sheepish now. Changed everything to float and works beautifully.Thanks again...
Antonio
+1  A: 

NSInteger can hold values up to the INT_MAX limit that equals 2147483647 - so your value overflows the integer types limit - remember that timeInterval is a double type.

You can try to use double type in all your calculations or use -timeIntervalSinceReferenceDate method - it returns interval since 1 January 2001 and you might avoid overflow as well.

If your events object is an array or other type that allows to get its size then you can add time interval values already divided by count - that also may help to avoid overflow:

NSTimeInterval runningSum = 0;
NSInteger count = [self.events count];
for (...){
...
runningSum += [dateFromString timeIntervalSince1970]/count;
}
Vladimir
true, thanks. Changed everything to float. This is what happens when you don't take a step back.
Antonio
A: 

NSInteger is a 32 bit signed integer on iPhone and is therefore limited to values between −2147483648 and +2147483647.

You may get the desired result by using NSUInteger which is an unsigned 32 bit integer able to contain values between 0 and +4294967295.

You should however pay attention to the number of runs through the loop so you don't wrap the values.

Claus Broch