“无符号长长”太小,无法表示数字

`unsigned long long` too small to represent number?

本文关键字:表示 数字 太小 无符号 无符号长长      更新时间:2023-10-16

我一直在试图得到欧拉项目问题 3 的答案,我需要找到600851475143的最大素因数,但我的程序挂在这个数字上,而不是更小的数字(有时是更大的数字)。我删除了该程序寻找素数分解的更一般的目的,希望它能减少计算时间,也许会给我一个答案,但它没有。以前,当程序从 1 而不是输入开始时,它给了我最低的素数 17,但仅此而已。现在它什么也没给我。

对于其他人来说,似乎有效的是增加数据类型的大小并将"ULL"附加到变量的末尾。这对我不起作用。其他人建议创建一个大数字类,但我的知识还不足以做到这一点,或者根本不使用类,真的。这是程序。

#include <iostream>
using namespace std;
bool is_prime(unsigned long long int input);
void factor_number(unsigned long long int input);
int main()
{
    unsigned long long int input = 600851475143ULL;
    cout << "Hello World!nn";
    if (is_prime(input) == false)
        factor_number(input);
    else
        cout << input << 1;
    cin.get();
    return 0;
}
bool is_prime(unsigned long long int input)
{
    for (int i = 1; i <= input; i++)
    {
        if (i != 1 && i != input)
        {
            if (input % i == 0)
            {
                return false;
            }
        }
        else if (i == input)
            return true;
    }
}
void factor_number(unsigned long long int input)
{
    unsigned long long int i = input;
    while (input % i != 0 || is_prime(i) == false)
    {
        i--;
    }
    cout << i << endl;
}
bool is_prime(unsigned long long int input)
{
    for (int i = 1; i <= input; i++)

unsigned long long int input可以存储值 [0,2^64)。

int i可以存储一个介于 [-(2^31),2^31) 之间的值。

i 2,147,483,647并且您递增它时,它变为负数,因此当input为>= 2^31 时,循环条件i <= input永远不会为假。如果i是一个unsigned int,则值>= 2^32时会出现问题。

#include <iostream>
#include <cstdint>
#include <limits>
int main() {
    int i = std::numeric_limits<int>::max();
    std::cout << i << "n";
    ++i;
    std::cout << i << "n";
}

现场演示:http://ideone.com/kmeXti

很有可能,当您比较iinput时,您的编译器会给您一个警告,但您选择忽略它。

您可以通过以下方式修复代码:

#include <cstdint>
bool is_prime(uint64_t input)
{
    for (uint64t_t i = 1; i <= input; ++i) {

---编辑---

您的素数函数也这样做:

for (int i = 1; i <= input; i++)
{
    if (i != 1 && i != input)
    {
循环

内的测试条件可能很昂贵(在本例中,您为循环的每次迭代进行测试)。如果您担心代码的性能,您应该做的第一件事就是尝试消除这些测试。

循环包含i != input测试 - 因此让我们将其提升到循环条件中:

for (uint64_t i = 1; i < input; i++)
{
    ...
}
return true;

现在我们不需要测试循环内的i != input,但我们仍然需要测试讨厌的 1。我们可以在开始时添加一些显式测试:

if (input < 4) {
    return (input > 1); // 2 and 3 are prime, 0 and 1 are not
}

但更重要的是,我们可以快速消除所有偶数。如果数字的最低位是"0",则数字为偶数:

if ((input & 1) == 0) // even number
    return false;

但是现在我们知道数字不可能是偶数,我们也可以少做除法测试。把所有的东西放在一起:

#include <iostream>
bool is_prime(uint64_t input)
{
    if (input < 4)
    {
        // eliminate 1, 2 and 3.
        return (input > 1);
    }
    // Eliminate even numbers
    if ((input & 1) == 0)
        return false;
    // we've eliminated even numbers, so the smallest
    // possible divisor is 3, start from there, but
    // we can also skip all even divisors!
    for (uint64_t div = 3; div <= input / 3; div += 2)
    {
        if ((input % div) == 0)
            return false;
    }
    return true;
}
int main()
{
    for (uint64_t i = 0; i < 64; ++i)
    {
        std::cout << i << ": " << (is_prime(i) ? "yes" : "no") << 'n';
    }
}

http://ideone.com/aJqApL