2

我有一个 C++ 程序,我将两个数字相除,我需要知道答案是否为整数。我正在使用的是:

if(fmod(answer,1) == 0)

我也试过这个:

如果(楼层(答案)==答案)

问题是答案通常是 5 位数字,但有很多小数。例如,答案可以是:58696.000000000000000025658并且程序认为是一个整数。

有什么办法可以使这项工作?

我在分double a/double b= double answer

(有时有超过 30 位小数)

谢谢!

编辑: a 和 b 是数千(约 100,000)的数字,然后将其提高到 2 和 3 的幂,加在一起并除以(根据复杂的公式)。所以我正在插入各种 a 和 b 值并查看答案。我只会保留使答案成为整数的 a 和 b 值。我得到的一个答案的一个例子是:218624,我上面的程序认为它是一个整数,但它确实是:218624.00000000000000000056982 所​​以我需要一个可以区分超过 20-30 个小数的整数的代码。

4

3 回答 3

1

您可以std::modf使用cmath.h

double integral;
if(std::modf(answer, &integral) == 0.0)

的整数部分answer存储在 中fraction,返回值为std::modf的小数部分,answer符号与 相同answer

于 2013-10-26T23:37:34.017 回答
1

通常的解决方案是检查数字是否在整数的非常短的距离内,如下所示:

bool isInteger(double a){
    double b=round(a),epsilon=1e-9; //some small range of error
    return (a<=b+epsilon && a>=b-epsilon); 
}

这是必需的,因为浮点数的精度有限,并且确实是整数的数字可能无法完美表示。例如,如果我们进行直接比较,以下将失败:

double d=sqrt(2); //square root of 2
double answer=2.0/(d*d); //2 divided by 2

在这里,answer实际上保存的是 value 0.99999...,所以我们无法将其与整数进行比较,也无法检查小数部分是否接近 0。通常,由于数字的浮点表示可以小一点或大一点与实际数字相比,小数部分是否接近0是不好的。可能是类似0.999999990.000001(甚至是它们的负数)的数字,这些都是精度损失的可能结果。这也是我检查双方(+epsilon-epsilon)的原因。您应该调整该epsilon变量以满足您的需求。

另外,请记住 a 的精度double接近15 位。您也可以使用 a long double,这可能会给您一些额外的精度(或不,这取决于编译器),但即使这样也只能让您获得大约18 digits。如果您需要比这更高的精度,则需要使用外部库,例如GMP

于 2013-10-27T00:12:16.990 回答
-1

浮点数使用与整数非常不同的位格式存储在内存中。因此,比较它们是否相等不太可能有效。相反,您需要测试差异是否小于某个epsilon

const double EPSILON = 0.00000000000000000001; // adjust for whatever precision is useful for you
double remainder = std::fmod(numer, denom);
if(std::fabs(0.0 - remainder) < EPSILON)
{
    //...
}

或者,如果您想包含接近整数的值(基于您所需的精度),您可以稍微修改 if 条件(因为返回的余数std::fmod将在 range 内[0, 1)):

if (std::fabs(std::round(d) - d) < EPSILON)
{
    // ...
}

你可以在这里看到这个测试。

浮点数通常精确到大约 12-15 位(作为 a double),但由于它们存储为尾数(分数)和指数,因此不太可能存储有理数(整数或常用分数)。例如,

double d = 2.0; // d might actually be 1.99999999999999995

因此,您需要将您期望的差异与包含您想要的精度的一些非常小的数字进行比较(我们将此值称为epsilon):

double d = 2.0;
bool test = std::fabs(2 - d) < epsilon; // will return true

因此,当您尝试比较 的余数时std::fmod,您需要检查它与 的差异0.0(而不是与 的实际相等0.0),这就是上面所做的。

此外,该std::fabs调用通过断言该值将始终为正来防止您进行 2 次检查。

如果您需要大于 15-18 位小数的精度,则不能使用doubleor long double; 您将需要使用高精度浮点库。

于 2013-10-27T00:01:05.113 回答