【问题标题】:cocoa - IF failing for double?可可 - 如果双倍失败?
【发布时间】:2010-03-18 11:50:19
【问题描述】:

我有一组这样的 NSTimeInterval:

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

在我的代码中的某个时刻,我想测试 currentTime 是否大于或等于数组中的时间之一,所以我这样做了

// currentTime = 18.32 right now
for (int i=0; i<[mySet count]; i++) {
  if (currentTime >= [[mySet objectAtIndex:i] doubleValue]) {
    NSLog(@"%d...", i);
  }
}

输出应该是“1...2...” 但输出只是“1 ...”

i = 1时, 它正在将 18.32 与 18.32 进行比较,并且无法识别该值等于或大于另一个?什么鬼???

怎么可能?

感谢您的帮助。

【问题讨论】:

    标签: iphone cocoa iphone-sdk-3.0


    【解决方案1】:

    通常在比较浮点值时,您想确定一个与另一个需要多接近(epsilon 或错误界限),然后只需检查它们是否在其中。最简单的方法是从另一个中减去一个,然后检查结果的绝对值是否小于或等于您的 epsilon

    伪代码:

     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
    

    【讨论】:

      【解决方案2】:

      如果您要进行精确计算,则不应使用 NSNumber,而应使用 NSDecimalNumber。前者只是将数字存储为对象的包装器,而后者旨在在进行计算时保持精度。它在极端范围内比标量工作得更好。

      Numbers and Values Programming Topics for Cocoa

      【讨论】:

        【解决方案3】:

        除某些情况外,您无法比较 double 值是否相等。 (1.00000 == 1.0000) 可能会响起,但 (1.3000 == 1.3000) 很可能不会。这是因为双精度数实际上不是十进制数。并不是所有的数字都可以用双精度表示;您的值可能类似于 18.320000123 和 18.320000473;也就是说;可能有很多尾随垃圾在您选择的精度下是无趣的,但仍然阻止它们进行同等比较。

        通过 NSNumber 运行其中一个也无济于事;两次。

        【讨论】:

          【解决方案4】:

          您将 var i 声明为 int,然后尝试将其 nslog 为 double 值而不进行强制转换。日志可能会失败,与您的测试精度无关。

          【讨论】:

            猜你喜欢
            • 2016-07-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-10
            • 2014-02-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多