[英]C++ determining if a number is an integer
我有一个用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个以上十进制小数的整数的代码。
您可以在cmath.h
使用std::modf
:
double integral;
if(std::modf(answer, &integral) == 0.0)
answer
的整数部分存储在fraction
, std::modf
的返回值是answer
的分数部分,其符号与answer
相同。
通常的解决方案是检查数字是否在整数的很短距离内,如下所示:
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
实际上保持值为0.99999...
,因此我们无法将其与整数进行比较,也无法检查小数部分是否接近0。通常,由于数字的浮点表示可以是一位小于或大于实际数字,则不宜检查小数部分是否接近0。它可能是0.99999999
或0.000001
(甚至它们的负数)之类的数字,这些都是精度损失的可能结果。 这就是为什么我要同时检查两面( +epsilon
和-epsilon
)。 您应该调整该epsilon
变量以适合您的需求。
另外,请记住, double
精度的精度接近15位数 。 您还可以使用long double
精度数,这可能会给您带来一些额外的精度数字(或者不是,这取决于编译器),但是即使这样也只能使您达到18位数左右。 如果您需要的精度更高,则需要使用外部库,例如GMP 。
浮点数使用与整数非常不同的位格式存储在内存中。 因此,比较它们的平等性不太可能有效。 相反,您需要测试差异是否小于某个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
返回的余数将在[0, 1)
范围内):
if (std::fabs(std::round(d) - d) < EPSILON)
{
// ...
}
您可以在此处查看此测试。
浮点数通常会精确到大约12至15位数(以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
调用通过断言该值始终为正值来防止您必须进行两次检查。
如果您希望精度达到小数点后15-18位,则不能使用double
或long double
; 您将需要使用高精度浮点库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.