You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSDecimalNumber与NSNumber比较返回错误结果问题咨询

为什么NSDecimalNumber与大整数NSNumber比较时isEqualToNumber:总是返回YES?

这个问题其实不是bug,而是由浮点数精度限制和isEqualToNumber:的比较逻辑共同导致的,我来给你拆解清楚:

首先看你提供的代码:

NSDecimalNumber *d1 = [NSDecimalNumber decimalNumberWithString:@"6560601600245628933"];
BOOL res = [d1 isEqualToNumber:@(6560601600245628934)];
NSLog(@"%@", @(res));

核心原因1:大整数无法被double精确表示

你用到的数字6560601600245628933和6560601600245628934都远大于2^53(也就是9007199254740992)——这是double类型能精确表示的最大整数。

当你用@(...)语法创建NSNumber时,编译器会把超出2^53的整数自动转换为double类型存储。但double的尾数只有53位,无法区分这些大整数之间的微小差异(比如差1),所以@(6560601600245628933)和@(6560601600245628934)实际上存储的是同一个double值。

核心原因2:isEqualToNumber:的跨类型比较逻辑

isEqualToNumber:方法在比较不同类型的数字对象时(比如NSDecimalNumber和普通NSNumber),会尝试将两者转换为同一种类型来对比。这里它会把NSDecimalNumber转换为double类型,再和NSNumber里的double值比较——既然两者的double值完全相同,自然会返回YES。

如何正确解决?

如果你需要精确比较这类超大整数,必须保证所有参与比较的数字都用NSDecimalNumber来创建,这样就能避免浮点数精度丢失:

NSDecimalNumber *d1 = [NSDecimalNumber decimalNumberWithString:@"6560601600245628933"];
NSDecimalNumber *d2 = [NSDecimalNumber decimalNumberWithString:@"6560601600245628934"];
BOOL res = [d1 isEqualToNumber:d2];
NSLog(@"%@", @(res)); // 这里会返回NO,符合预期

或者,如果你必须使用NSNumber,也可以用initWithDecimal:方法基于NSDecimal来创建,确保精度不丢失。

内容的提问来源于stack exchange,提问作者KudoCC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:40:01