【问题标题】:Multiplication and Division unsigned integers无符号整数的乘法和除法
【发布时间】:2017-10-18 18:31:15
【问题描述】:

在我的程序中,我必须对无符号整数进行算术运算。

  • 变量 a 的范围是 0 到 4294967295。
  • 变量 b 的范围是 0 到 32。

当我通过取 a 和 b 的最大值来检查边界条件时,我得到 0 作为答案,因为当我尝试将 a 和 MAX_NS 相乘时发生溢出>。理想情况下,我应该得到 7 作为答案。我如何编写程序以处理溢出问题,我得到 7 作为答案,希望它适用于 a 和 b 的其他有效值范围。谢谢。

#include "stdio.h"

#define MAX_NS 1000000000

 int main()
 {
    unsigned int a =  4294967295;
    unsigned int b =  32 ;

    unsigned int c = ((b * MAX_NS)/a);
    printf("%d",c);


 }

**编辑:**请注意,我不能使用 unsigned long long。我只能对变量使用 unsigned int。

【问题讨论】:

  • 使用unsigned long long?您正在除以最大无符号值,因此在unsigned int 范围内的所有结果(除了一个)将是0。
  • 没有办法单独使用操作顺序来获得与使用任意大小的中间体执行计算时相同的结果。您可能可以使用特定于输入值的技巧(最简单的:c = 7;),但除此之外,您能做的最好的事情就是显式提升为更广泛的类型,例如 uintmax_t。
  • 我不明白你为什么期望答案是 7。完全精确的答案将有五个低位全为零,而高于该位的 32 位全为 1。你如何从中得到 7 个?
  • "...对无符号整数执行算术运算。...a 的范围为 0 到 4294967295"。嗯,除法当然是“`1 to 4294967295”。
  • #define MAX_NS 1000000000 --> #define MAX_NS 1000000000ull

标签: c time overflow unsigned multiplication


【解决方案1】:

这是Weather Vane建议的解决方案

#include "stdio.h"

#define MAX_NS 1000000000

int main()
{
    unsigned long long a = 4294967295;
    unsigned long long b = 32;

    unsigned long long c = ((b * MAX_NS) / a);
    printf("%llu", c);
}

【讨论】:

  • 但即使我使用较小的 'a' 值(假设 50000000),我也没有得到正确的答案。应该是 640 但我得到了 38。可能是什么原因?
  • 肯定有其他问题。我检查了这段代码,它打印了 7。
  • @GopalaKrishna 在您的示例中 b * MAX_NS 是 32000000000,它太大而无法存储在 32 位 unsigned int 中,无论您然后除以 什么。
  • 您要显示打印屏幕吗?正如我告诉过你的,问题是其他问题,而不是代码。
  • 我改了主程序:unsigned int a = 50000000;无符号整数 b = 32 ;无符号整数 c = ((b * MAX_NS)/a); printf("%d",c);.我得到 38 作为答案
【解决方案2】:

关键是乘积 b * MAX_NS 必须使用足够宽的数学计算。

确保至少有一个* 操作数是unsigned long long。

b 足够大,a 足够小,商将需要更宽的类型以避免溢出;

#include "stdio.h"
// #define MAX_NS 1000000000
#define MAX_NS 1000000000LLU

int main(void) {
  unsigned int a =  4294967295;  // type may remain unsigned 
  unsigned int b =  32 ;         // type may remain unsigned 

  unsigned long long c = ((b * MAX_NS)/a);
  printf("%llu",c);
}

或者,通过乘以 1ull 来温和地诱导乘法。通常避免像(unsigned long long) b * MAX_NS 那样进行强制转换。有时会出人意料地缩小可能在uintmax_t b这里发生的数学运算的猖獗做法。

#define MAX_NS 1000000000

int main(void) {
  unsigned int a =  4294967295;  // type may remain unsigned 
  unsigned int b =  32 ;         // type may remain unsigned 

  unsigned long long c = ((1ull * b * MAX_NS)/a);
  printf("%llu",c);
}

【讨论】:

  • 感谢您的回答,但我们的硬件仅支持 32 位,不能使用 unsigned long long..
  • @GopalaKrishna 即使是 8 位处理器也可以支持 unsigned long long。兼容的 C 编译器将形成实现 64 位类型和数学的必要指令。 original 帖子中应包含“仅使用最多 32 位数学”之类的不寻常要求。
猜你喜欢
  • 2013-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
  • 2015-05-30
相关资源
最近更新 更多