用c ++中的平方数,Kaprekar数

时间:2015-12-24 04:54:14

标签: c++ numbers multiplying

在检测某个范围内的Kaprekar数时,在C ++中发现了这个问题。编号为77778 -

unsigned long long sq = pow(n, 2);

时返回6,049,417,284
unsigned long long sq = n * n;

返回1,754,449,988

任何想法为什么?这是什么样的溢出,功率可以避免,但正常的n * n不会。

3 个答案:

答案 0 :(得分:2)

假设您的n是典型的intunsigned int,原因是

这一行

unsigned long long sq = n * n;

相当于

unsigned long long sq = (int)(n * n);

因为在将结果赋给sq之前,首先会处理n * n(两者都是整数)。所以,这是一个溢出问题(欢迎使用 Stack Overflow 也是!)。

您可能还想通过搜索来了解这些术语overflowcasting(因为它们是计算中非常常见的问题,早期了解它们会有很大的帮助!)。

这与Kaprekar数字无关。在大多数情况下,机器int是32位。因此,它只能处理值-2,147,483,648到2,147,483,647(或无符号整数计数器部分的0到4,294,967,295)。

因此处理n * n会给你:

n * n = 6,049,417,284 - 4,294,967,296 = 1,754,449,988 //overflow at (4,294,967,295 + 1)!

如果您事先进行施法:

unsigned int n = 77778;
unsigned long long sq = pow(n, 2);
unsigned long long sq2 = (unsigned long long)n * n; //note the casting here.
std::cout << sq << std::endl;
std::cout << sq2 << std::endl;

然后结果将是相同的,因为不会有溢出

答案 1 :(得分:2)

您的n被声明为32位int。您需要将其更改为long long或将操作强制转换为long long。

unsigned long long sq=(unsigned long long)n*n;

这将给出正确答案

答案 2 :(得分:1)

我怀疑n被声明为unsigned int,并且您的编译器使用的数据模型假定int为32位宽。可以使用此类型表示的最大值为2 32 - 1 = 4294967295。超出此值的任何值都将会回滚。因此,分配4294967296将变为0,4294967297将变为1,依此类推。

你有溢出;由于两个操作数均为unsigned int,因此结果类型也是相同的。该操作的真实结果是6049417284.将其分配给unsigned int将(换行)并变为1754449988 = 6049417284 - 4294967296.此unsigned int结果被分配给更宽的类型unsigned long long,它没有改变价值。理解结果的类型(表达式的类型)和目标类型(将保存结果的变量的类型)之间的区别是必要的。

无符号类型中的环绕行为(更正式地模n)在C ++中是明确定义的,因此编译器可能不会警告您。

引自Unsigned Arithmetic

  

如果无符号整数溢出,则结果以模2 w 定义,其中w是该特定无符号整数中的位数。通过暗示,无符号整数永远不会为负。