C ++检查double是否为整数在某些情况下不起作用

时间:2017-06-06 02:58:25

标签: c++ integer double

我正在尝试打印出遵循某个规则的前几个数字:它的数字之和可以提升到一个整数幂来获得数字本身。 (基本上如果总和是数字的第n个根)。

例如,数字81中的数字之和为9,而9 ^ 2为81。

这是我正在使用的一些代码:

#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <math.h>
using namespace std;

int sumOfDigits(int num) {
    int sum = 0;
    string numStr = "";
    stringstream s;
    s << num;
    s >> numStr;
    for (int i = 0; i < numStr.length(); i++) {
        int ad = 0;
        stringstream ss;
        ss << numStr[i]; // take each digit
        ss >> ad;
        sum += ad; // and add to sum
    }
    return sum;
}

int num = 10; // starting number
int numFound = 0; // how many such special numbers have been found

int main() {
    while (numFound < 5) {
        int sum = sumOfDigits(num);
        double exp = log10(num) / log10(sum);

        if (fmod(exp, 1.0) == 0.0 && sum != 1) { // if the exponent is an integer
            cout << num << "\t" << sum << endl; // then print out the number and the sum of its digits
            numFound++;
        }
        num++;
    }

    return 0;
}

当我运行它时,我得到以下输出:

81      9
2401    7
4913    17
5832    18
17576   26

第二个条目应该是5128,因为8 ^ 3是512.我不明白为什么测试适用于某些数字但不能与其他人一起工作。

我已经尝试过测试指数是否也是整数的其他方法。我已根据floor()表达式对其进行了测试,并且我尝试使用(int)投射整个表达式。

我可能错了,问题可能不在那个地方,但如果你能帮助我,我会非常感激。谢谢。

2 个答案:

答案 0 :(得分:1)

检查浮点数之间的相等性如下:fmod(exp, 1.0) == 0.0必然会给您带来麻烦。例如,只需更改您的代码:

#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <math.h>
#include <limits>
using namespace std;

int sumOfDigits(int num) {
    int sum = 0;
    string numStr = "";
    stringstream s;
    s << num;
    s >> numStr;
    for (int i = 0; i < numStr.length(); i++) {
        int ad = 0;
        stringstream ss;
        ss << numStr[i]; // take each digit
        ss >> ad;
        sum += ad; // and add to sum
    }
    return sum;
}

int num = 10; // starting number
int numFound = 0; // how many such special numbers have been found

int main() {
    while (numFound < 5) {
        int sum = sumOfDigits(num);
        double exp = log10(num) / log10(sum);

        if (fabs(fmod(exp, 1.0)) < std::numeric_limits<float>::epsilon() && sum != 1) { // if the exponent is an integer
            //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            cout << num << "\t" << sum << endl; // then print out the number and the sum of its digits
            numFound++;
        }
        num++;
    }

    return 0;
}

我可以得到这个输出:

81  9
512 8
2401    7
4913    17
5832    18

因此,使用合适的epsilon值或只是坚持整数。

请阅读:

What is the most effective way for float and double comparison?

答案 1 :(得分:0)

循环求和和指数会快得多:

unsigned int number;
unsigned int min_sum =   3;
unsigned int max_sum = 100;
unsigned int min_exp =   2;
unsigned int max_exp =  20;

int main() {
    for (unsigned int exp = min_exp; exp <= max_exp; ++exp) 
        for (unsigned int sum = min_sum; sum <= max_sum; ++sum) {
            number = pow(sum, exp);
            if ( sumOfDigits(number) == sum ) 
                cout << numFound++ << ":\t" << number << "\t = " << sum << " ^ \t" << exp << endl;
        }
    return 0;
}