【问题标题】:Code Blocks 10.05 and 12.11, 13.12 returns different results with same code代码块 10.05 和 12.11、13.12 使用相同的代码返回不同的结果
【发布时间】:2014-01-05 01:01:00
【问题描述】:

我写了下面的代码来判断一个数字是否是回文。但是当我编译并运行代码时,它会在代码块 10.05 和 12.11、13.12 中返回不同的结果。

我尝试了编号为 12321 的代码。代码块 10.05 返回“编号 12321 有 5 位,是一个回文数”。代码块 12.11 和 13.12 返回“数字 12321 有 5 位,不是回文数”。

这里是代码。

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
    int num, tmp, tmp2, i, k, last_num=0, check_num;

    cout<<"Enter a number : ";
    cin>>num;

    tmp=num;
    check_num=num;

    for(i=1; tmp>=10; ++i)
    {
        tmp=(tmp-(tmp%10))/10;
    }

    cout<<"The number "<<num<<" has "<<i<< " digits ";
    for(k=i-1; k>=0; k--)
    {
        tmp2 = num%10;
        last_num+=tmp2*pow(10,k);

        num=(num-(num%10))/10;
    }

    if(check_num == last_num)
    {
        cout<<"and is a palindrome number"<<endl<<endl;
    }
    else
    {
        cout<<"and is NOT a palindrome number"<<endl<<endl;
    }

    return 0;
}

【问题讨论】:

  • 闻起来像未定义的行为。不过,我没有看到您尝试在调试器中检查您的代码。此外,使用pow() 计算整数幂是错误的,因为该函数返回的值不准确。
  • 嘿,新版本的 CodeBlocks。无论如何,这将是 GCC 4.4.1、GCC 4.7.(umm)1 的区别?以及新版本使用的任何内容,除非您更改了其中任何一个。
  • 加上 H2CO3 所说的,你在某个时候计算出pow(10,-1)。然后你将它乘以某个东西并将结果转换为一个 int。不同的编译器版本可能会发生不同的舍入。
  • @Floris 不,它很可能不会更快,而且肯定不会更干净。这是一个没有字符串的数学问题使用。我能想到的最佳解决方案是使用模运算 (int k = 0; while (n) { k *= 10; k += n % 10; n /= 10; }) 以相反的顺序构建数字,然后检查新获得的数字是否与原始数字匹配。
  • @Floris 谢谢,很有趣。似乎除法(无论是正则还是模) 比从内存中读取要慢。我现在很着急,所以我没有时间检查组件,但我相信这可以解释它。另外,我很想知道如果转换以二进制、八进制或十六进制进行会有什么不同(只是为了使算术运算可以优化为按位运算)。虽然在您的特定实现上速度更快,但是使用字符串并没有成为“正确的解决方案 (TM)”——我们有一个数学问题的事实并没有改变。

标签: c++ codeblocks


【解决方案1】:

您的代码过于复杂且不正确(因为我已经提到过浮点数的问题,即pow() 返回的值可能不准确)。

您可以用一种更简单、更简洁的方式来实现这一点:以相反的顺序从数字开始构建数字,然后检查以这种方式获得的数字是否与原始数字匹配:

int ispal(unsigned long long n)
{
    unsigned long o = n;
    unsigned long long k = 0;
    while (n) {
        k *= 10;
        k += n % 10;
        n /= 10;
    }

    return o == k;
}

unsigned long long 仅用于代替普通的int 以使此函数适用于尽可能大的数字。)

【讨论】:

  • 它可能返回bool而不是int
  • 感谢您的回答。现在它正常工作。但是我仍然不清楚为什么我的代码在 CB 10.05 上正常工作,而在 CB 12.11、13.12 上却不工作?可能是关于上面@chris 评论的编译器,或者可能是另一个原因?
  • @Bilal 同样,pow() 和/或其他东西。是时候启动调试器了。
【解决方案2】:

跟进我和H2CO3的评论帖,我在这里提供一下字符串法和数字法检查回文的比较:

#include <iostream>
#include <string>
#include <ctime>

int ispal(unsigned long long n)
{
    unsigned long long o = n;
    unsigned long long k = 0;
    while (n) {
        k *= 10;
        k += n % 10;
        n /= 10;
    }

    return o == k;
}

int ispalc(char* s)
{
    char *e;
    e = s + strlen(s) - 1;
    while(s < e)
    {
      if( *s++ != *e-- ) return 0;
    }
    return 1;
}

int main(void) {
    unsigned long long num;
    int ii;
    time_t startT, endT, diff1, diff2;
    char nums[128];

    std::cout<<"Enter a number : ";
    std::cin>>num;

    if (ispal(num) != 0) std::cout << "It is a palindrome" << std::endl;
    else std::cout << "It is not a palindrome" << std::endl;

    sprintf(nums, "%lld", num);

    if (ispalc(nums) != 0) std::cout << "It is a palindrome" << std::endl;
    else std::cout << "It is not a palindrome" << std::endl;
    startT = clock();
    for(ii = 0; ii < 1000000; ii++) ispal(num);
    endT = clock();
    diff1 = (endT - startT);

    startT = clock();
    for(ii = 0; ii < 1000000; ii++) ispalc(num);
    endT = clock();
    diff2 = (endT - startT);

    printf("using numbers: %.2lf us\n", diff1 * 1000.0 / CLOCKS_PER_SEC );
    printf("using strings: %.2lf us\n", diff2 * 1000.0 / CLOCKS_PER_SEC );
    return 0;
}

需要注意的几点:

  1. 我将字符串到数字和数字到字符串的转换留在了计时循环之外。由于用户输入实际上是一个字符串(被转换为一个数字),这给了 number 方法一个优势。在“现实生活”中,将字符串转换为数字将是整个过程中较慢的操作之一。
  2. 我在主层也做了数字unsigned long long的类型;以及函数内部o 的类型(它是unsigned long)。这使得代码稍微快了一点,因为它没有花时间进行转换。

鼓声……结合上述注意事项,计时性能是:

Enter a number : 123454321
It is a palindrome
It is a palindrome
using numbers: 68.51 us
using strings: 26.27 us

Enter a number : 1234567
It is not a palindrome
It is not a palindrome
using numbers: 53.03 us
using strings: 11.78 us

赢家对我来说似乎很清楚 - “字符串有它”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    相关资源
    最近更新 更多