NSDecimalNumber integerValue 在 iOS8 中表现异常
Posted
技术标签:
【中文标题】NSDecimalNumber integerValue 在 iOS8 中表现异常【英文标题】:NSDecimalNumber integerValue behaving strangely in iOS8NSDecimalNumber integerValue 在 iOS8 中表现异常 【发布时间】:2014-09-06 22:52:34 【问题描述】:好的团队,这很奇怪。 [NSDecimalNumber integerValue] 行为异常。
我正坐在断点处,试图找出为什么我的应用程序的某些部分在 ios8 中被破坏,我正在查看一个名为“timeSeconds”的变量。它在 Xcode 变量视图中如下所示:
_timeSeconds (NSDecimalNumber *) 344.514533996581994496
但是当我在调试器中查询它时,我看到了这个:
(lldb) p [self.timeSeconds doubleValue]
(double) $14 = 344.51453399658192
(lldb) p [self.timeSeconds intValue]
(int) $15 = 344
(lldb) p [self.timeSeconds integerValue]
(NSInteger) $16 = -5
(lldb) p (NSInteger)[self.timeSeconds intValue]
(NSInteger) $17 = 344
看到那个“-5”了吗?在我提交雷达之前,你们中的任何一个漂亮的人都可以复制或解释一下吗?
这里是 SSCCE:
NSDecimalNumber *n = [NSDecimalNumber decimalNumberWithString:@"344.514533996581994496"];
NSLog(@"%@", n); // 344.514533996581994496
NSLog(@"%ld", (long)[n intValue]); // 344
NSLog(@"%ld", (long)[n integerValue]); // -5
NSLog(@"%ld", (long)[n unsignedIntegerValue]); // 12
提前致谢!
马修
【问题讨论】:
马修 - 你发现了什么? iOS 8 上的 NSDecimalNumber 在我的实时应用程序中造成了巨大的问题! 【参考方案1】:integerValue 的结果令人惊讶,但据我所知,记录如下:
NSDecimalNumber 继承自 NSNumber。在 NSNumber 的子类注释中指出 "...子类必须覆盖与声明类型对应的访问器方法——例如,如果您的 objCType 实现返回“i”,则必须覆盖 intValue ..."
objCType 设置为内部指针,因此它应该与 NSNumber 相同。
NSDecimal 不会覆盖 intergerValue。 它确实覆盖了 doubleValue,所以应该可以正常工作。
唯一让我好奇的是:它似乎也没有覆盖 intValue ...
【讨论】:
我认为你绝对是在正确的轨道上。我想更好地理解这一点,如果您确实了解 intValue,请发布您的答案。但我会继续奖励赏金,因为我认为这是正确的方向,我不希望赏金在没有奖励给你的情况下用完。 这是一个相关问题,其中有一个更具体的 NSDecimal 问题可能与此问题有关。 ***.com/questions/26741233/…【参考方案2】:多么大的错误!我只是发现自己被它欺骗了。所以,总结一下dogsgods的回答:
不要:
NSInteger x = [myDecimalNumber integerValue];
相反,这样做:
NSInteger x = (NSInteger)[myDecimalNumber doubleValue];
【讨论】:
【参考方案3】:使用myDecimalNumber.intValue
而不是integerValue
【讨论】:
【参考方案4】:你可以使用 intValue 或 unsignedIntValue 就好了,但是 NOT integerValue 或 unsignedIntegerValue。这是一个演示该问题的单元测试,表明它与需要超过 64 位精度的数字有关:
//
// NSDecimalNumberBugTests.m
//
// Created by Lane Roathe on 6/1/17.
// For Quicken, Inc.
//
#import <XCTest/XCTest.h>
@interface NSDecimalNumberBugTests : XCTestCase
@end
@implementation NSDecimalNumberBugTests
- (void)setUp
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
- (void)tearDown
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
- (void)testBug
// Use XCTAssert and related functions to verify your tests produce the correct results.
NSDecimalNumber* decimalLength;
NSUInteger interval;
// Start with a number that requires 65+ bits
// This FAILS (interval is zero)
decimalLength = [NSDecimalNumber decimalNumberWithString:@"1.8446744073709551616"];
interval = decimalLength.unsignedIntegerValue;
XCTAssert(interval == 1);
// This Works, interval is 1
interval = decimalLength.unsignedIntValue;
XCTAssert(interval == 1);
// Now test with a number that fits in 64 bits
// This WORKS (interval is 1)
decimalLength = [NSDecimalNumber decimalNumberWithString:@"1.8446744073709551615"];
interval = decimalLength.unsignedIntegerValue;
XCTAssert(interval == 1);
@end
【讨论】:
以上是关于NSDecimalNumber integerValue 在 iOS8 中表现异常的主要内容,如果未能解决你的问题,请参考以下文章