如何正确地乘以两个长多头?

时间:2010-08-22 15:59:55

标签: c multiplication unsigned-long-long-int

我希望乘以2 ^ 32基数给出的长数。我已经想到了一个很好的算法来做到这一点,但不幸的是我被卡住了。我坚持的情况是,我是如何将两个长整数相乘并以2 ^ 32为基础表示它。

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef unsigned int uint32;
typedef unsigned long long uint64;
int main(int argc, char* argv[] )
{

  uint64 a = (uint64)ULONG_MAX;
  printf("%llu\n", a);
  uint64 b = (uint64)ULONG_MAX;  
  printf("%llu\n", b);  
  uint64 c = (uint64)(a*b);

  printf("%llu\n", c);  // prints 1. that would be to lower 32 bits of the results. the upper half is 0xFFFFFFFE

  printf("%llu\n", ULLONG_MAX);
  system("pause");
}

为什么ULLONG_MAX与ULONG_MAX相同?根据{{​​3}},它应该是18,446,744,073,709,551,615 I

从我的评论中可以看出,我想要两个uint32中的multiplikation的结果。 lowerhalf为0x1,上半部分为0xFFFFFFFE。我如何获得这些值?

(我在SO上发现了这个问题,但这对我的情况没有帮助,因为给出的答案与我的想法类似:http://en.wikipedia.org/wiki/Limits.h#Member_constants

修改 我的系统是Windows XP 32位。我正在使用gcc 3.4.2(mingw-special)

我在运行代码时得到的输出:

4294967295
4294967295
1
4294967295

EDIT2:

  printf("%i\n", sizeof(unsigned long));
  printf("%i\n", sizeof(unsigned long long)); 

返回

4
8

编辑3: 感谢Petesh,我找到了解决方案:

  printf("%lu\n", c & 0xFFFFFFFF);
  printf("%lu\n", (c >> 32));

2 个答案:

答案 0 :(得分:5)

提示在系统中(“暂停”) - 你在Windows上?使用Microsoft visual c运行时打印很长时间需要使用'%I64u'(这是大写i)。

这是基于问题How do you printf an unsigned long long int(the format specifier for unsigned long long int)?

答案 1 :(得分:3)

不确定为什么你用你的(未指定的)编译器获得这些结果,但是在Ubuntu 10下的gcc给出了:

4294967295
4294967295
18446744065119617025
18446744073709551615

最后两个分别是0xfffffffe00000001和(2 64 -1),如你所愿。

因此,可以考虑切换到更新的编译器。您可能正在使用C99之前的编译器。

只是出于兴趣,sizeof (unsigned long)sizeof (unsigned long long)会为您提供系统支持。这对解释你的问题大有帮助。


要检查的其他几件事情,因为您的sizeof似乎表明数据类型本身是正常的(尽管这些可能无法解决问题 - 它们是fairly shallow web search发现的):

  • 尝试使用"%I64u"作为格式字符串而不是"%llu"。如果MinGW正在使用MSVCRT库,则可能需要真正的64位printf支持。
  • 确保您使用-std=c99进行编译。