我在这里遇到了一个奇怪的问题,我确信它只是一些小问题。
我通过JSON收到有关文件的信息(RestKit做得很好)。 我通过coredata将每个文件的文件大小写到本地商店。
之后在我的一个视图控制器中,我需要总结数据库中所有文件的文件大小。我获取所有文件然后通过斜率(for)来增加大小。
问题是现在,结果总是消极的!
coredata实体filesize的类型为Integer 32(filesize由JSON以字节为单位报告)。
我在NSArray allPublicationsToLoad
中阅读了fetchresult,然后尝试总结。类型为CDPublication
的NSArray中的对象具有类型NSNumber的值filesize
:
for(int n = 0; n < [allPublicationsToLoad count]; n = n + 1)
{
CDPublication* thePub = [allPublicationsToLoad objectAtIndex:n];
allPublicationsSize = allPublicationsSize + [[thePub filesize] integerValue];
sum = [NSNumber numberWithFloat:([sum floatValue] + [[thePub filesize] floatValue])];
单个CDPublications对象的每个单个文件大小都是正确且正确的。之后只有所有文件大小的总和为负。目前大约有240个对象,filesize-values介于4000和234.645.434.123之间。
请有人请给我一个正确的方向! 这是Integer 32或NSNumber无法容纳这么大范围的问题吗?
由于
MadMaxApp }
答案 0 :(得分:4)
NSNumber对象无法容纳如此庞大的数字。由于存储负数的方式,结果是否定的。
使用two's complement存储负数,这样可以更容易地添加正数和负数。 NSNumber可以容纳的数字范围分为两部分,最高一半(最高阶位等于1的int值)被认为是负数,最低一半(最高阶位等于0)是正常的正数。现在,如果添加足够大的数字,结果将在最高的一半,因此被解释为负数。这是一个4位整数情况的例子(32个完全相同,但是会有更多的0和1来输入;)
使用4位可以表示此有符号整数范围:
0000 (=0)
0001 (=1)
0010 (=2)
...
0111 (=7)
1000 (=-8)
1001 (=-7)
...
1111 (=-1)
在这种情况下,您可以表示的最大正整数为7。如果您要添加5和4,例如,您将得到:
0101 + 0100 = 1001
当你表示这样的有符号整数时,1001等于-7(而不是9,正如你所期望的那样)。这是你观察到的效果,但是规模要大得多(32位)
在这种情况下获得正确结果的唯一选择是增加用于表示整数的位数,因此结果不会位于位组合的负数范围内。因此,如果32位不够(就像你的情况一样),你可以使用长(64位)。
[myNumber longLongValue];
答案 1 :(得分:3)
我认为这与int
溢出有关:非常大的整数在溢出int
(32位)的大小时会被重新解释为负数。使用longLongValue
代替integerValue
:
long long allPublicationsSize = 0;
for(int n = 0; n < [allPublicationsToLoad count]; n++) {
CDPublication* thePub = [allPublicationsToLoad objectAtIndex:n];
allPublicationsSize += [[thePub filesize] longLongValue];
}
答案 2 :(得分:2)
这是与使用two's complement arithmetic相关的整数溢出问题。对于32位整数,可以表达恰好2个 32 (4,294,967,296)个可能的整数值。当使用二进制补码时,最高有效位用作符号位,允许一半数字表示非负整数(当符号位为0时),另一半表示负数(当符号位为1时) )。这给出了[-2 31 ,2 31 -1]或[-2,147,483,648,2,147,483,647]的有效范围。
要针对您的情况克服此问题,您应该考虑使用64位整数。这应该适用于您似乎有兴趣使用的值范围。或者,如果即使64位还不够,你也应该为iOS寻找大整数库。