【问题标题】:Integer multiplication overflow整数乘法溢出
【发布时间】:2015-03-30 00:49:10
【问题描述】:

我在 Objective C 中将两个整数相乘时遇到问题。当我将 500 与 20000000 相乘并保存在一个 long 变量中并打印它时,结果是 141006540​​8

int x = 500;
long myLongValue = x * 20000000;
NSLog(@" %lu",myLongValue);

我认为问题在于整数溢出,但我找不到真正的原因。我尝试使用这些整数的乘法来找到真正的结果 10000000000。有可能吗?

【问题讨论】:

    标签: objective-c integer overflow long-integer


    【解决方案1】:

    这里有一个溢出:unsigned int 使用 32 位编码,因此最大值将为 2^32-1, 4294967295。int 使用 31 位编码(1 位用于符号),最大值将是 2147483647。

    正如您在此处看到的,33h 位用于表示您的数字,因此您不能用 int 表示它。猜猜如果将此位设置为 0 会得到哪个数字? ;)

    已编辑解决方案:即使您将结果分配给 long 值,结果也会首先存储到 int 中,因此您应该在 objC 中执行乘法之前将值转换为 long。此外,正如 rmaddy 在 cmets 中注意到的那样,使用 long 变量在 32 位架构中不起作用,因为 long 是使用 4 字节编码的。您应该改用long long 类型,或者使用显式类型,例如 int32_t 和 int64_t。

    int x = 500;
    long long myLongValue = (long long)x * 20000000;
    NSLog(@" %llu",myLongValue);    // logs correctly 10000000000
    

    您也可以将x 直接声明为long long 变量。

    仅供参考: swift 不像 objC 那样宽容,您的示例代码会因为“超出范围”位而崩溃:

    let a:Int32 = 20000000
    let b:Int32 = 500
    
    let result = a*b                    // CRASH
    let result2 = Int64(a)*Int64(b)     // OK
    

    【讨论】:

    • 问题是关于Objective-C的。最好在 Objective-C 中发布答案,而不是 Swift。
    • 抱歉含糊不清,关于 swift 的最后一段是为了表明这种新语言在运行时不太容易出现错误,因为您在编译时遇到了错误。
    • 好的,但问题的实际答案将包括使用适当语言的适当解决方案。保留 Swift 来演示问题,但在 Objective-C 中添加解决问题的解决方案。
    • 添加了objC中的答案:)
    • 奇怪。当我在第 5 代 iPod touch 上运行发布的解决方案时,它仍然显示错误的答案。我需要将myLongValue 和演员更改为long long 才能看到正确的答案。
    猜你喜欢
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-27
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    相关资源
    最近更新 更多