开发者

cocoa - IF failing for double?

开发者 https://www.devze.com 2022-12-24 09:59 出处:网络
I have a set of NSTimeIntervals like this: NSArray *mySet = [NSArray arrayWithObjects: [NSNumber numberWithDouble: time1], //

I have a set of NSTimeIntervals like this:

NSArray *mySet = [NSArray arrayWithObjects:
  [NSNumber numberWithDouble: time1], //
  [NSNumber numberWithDouble: time2], 
  [NSNumber numberWithDouble: time3], 
  nil];

// suppose that at this time
// time1 = 0.00000
// time2 = 18.3200
// time3 = 21.6500

at some point in my code I want to test if currentTime is greater or equal to one of the times on the array, so I do

// currentTime = 18.32 right now
for (int i=0; i<[mySet count]; i++) {
  if (currentTime >= [[mySet objectAtIndex:i] doubleV开发者_StackOverflow中文版alue]) {
    NSLog(@"%d...", i);
  }
}

The output should be "1...2..." but the output is just "1..."

when i = 1, it is comparing 18.32 to 18.32 and failing to recognize that the value is equal or greater than the other? WTF???

How can that be?

thanks for any help.


Typically when comparing floating point values you want to decide how close one needs to be to the other (an epsilon or error bound), then just check if they are within that. The easiest way to do that is subtract one from the other then check if the absolute value of the result is less than or equal to your epsilon.

Pseudocode:

 var values = [...];
 var toCheck = ...;
 var epsilon = 0.00001;

 for (var i = 0; i < length(values); ++i)
      if (abs(values[i] - toCheck) <= epsilon)
          print "they are close enough"
      end
 end


If you're trying to do precise calculations, you shouldn't use NSNumber but NSDecimalNumber. The former is just a wrapper for storing numbers as objects whereas the second is designed to preserve precision when doing calculations. It works better than scalars at extreme ranges.

See Numbers and Values Programming Topics for Cocoa


You can't compare double values for equality except for certain cases. (1.00000 == 1.0000) would probably ring true, but (1.3000 == 1.3000) would most likely not. This is because doubles aren't actually decimal numbers; and not all numbers can be represented by a double; your values are likely something like 18.320000123 and 18.320000473; that is to say; there's probably a lot of trailing garbage that is uninteresting at the precision you have chosen, but none the less keep them from comparing as equal.

It doesn't help that you run one of them through NSNumber; twice.


You declare var i as an int and then try to nslog it at as double value without a cast. The log might be failing independent of the precision of your test.

0

精彩评论

暂无评论...
验证码 换一张
取 消