测试浮点数是否为整数
此代码有效(C3)
double d; if(d == (double)(int)d) ...;
- 有一个更好的方法吗?
- 由于种种原因,我想避免双重投票。除此以外还有哪些不错的方法? (即使它们不那么好)
注意:几个人指出(重要)一点,即==通常是有问题的重整浮点数。在这种情况下,我期望值在0到几百之间,并且它们应该是整数(非整数是错误),因此,如果这些点"不应该"对我来说是个问题。
解决方案
我们不需要那里多余的(双精度)。这有效:
if (d == (int)d) { //... }
d == Math.Floor(d)
换句话说,做同样的事情。
注意:希望我们知道在做这种事情时必须非常小心;浮点数/双精度数将很容易累积微小的错误,这些错误会使精确的比较(如此)没有明显的原因而失败。
像这样
double d = 4.0; int i = 4; bool equal = d.CompareTo(i) == 0; // true
使用Math.Truncate()
如果double是另一次计算的结果,则可能需要以下内容:
d == Math.Floor(d + 0.00001);
这样,如果有轻微的舍入错误,它仍然会匹配。
我认为这可以工作:
if (d % 1 == 0) { //... }
我无法回答问题中特定于C#的部分,但是我必须指出,我们可能缺少带浮点数的通用问题。
通常,浮点数没有很好地定义整数。出于同样的原因,在浮点数上没有很好地定义相等性。浮点计算通常包括舍入误差和表示误差。
例如," 1.1 + 0.6!= 1.7"。
是的,这就是浮点数的工作方式。
这里," 1.1 + 0.6 1.7 == 2.2204460492503131e-16"。
严格来说,与浮点数比较最接近的事情是将浮点数与选定精度进行比较。
如果这还不够,则必须使用十进制数表示形式,具有内置误差范围的浮点数表示形式或者符号计算。
如果我们只是要转换它,Mike F / Khoth的回答很好,但还不能完全回答问题。如果我们要进行实际测试,并且确实很重要,那么我建议我们实施一些包含错误余量的操作。
例如,如果我们正在考虑使用钱,并且想要测试偶数金额,我们可能会说(遵循Khoth的模式):
if( Math.abs(d - Math.Floor(d + 0.001)) < 0.001)
换句话说,取值之差的绝对值和它的整数表示并确保它很小。
这将让我们选择所需的精度,加上或者减去半个刻度,以解决浮点漂移问题。比较也是不可或者缺的,这很好。
static void Main(string[] args) { const int precision = 10000; foreach (var d in new[] { 2, 2.9, 2.001, 1.999, 1.99999999, 2.00000001 }) { if ((int) (d*precision + .5)%precision == 0) { Console.WriteLine("{0} is an int", d); } } }
和输出是
2 is an int 1.99999999 is an int 2.00000001 is an int
你能用这个吗
bool IsInt(double x) { try { int y = Int16.Parse(x.ToString()); return true; } catch { return false; } }