为什么Math.Floor(Double)返回Double类型的值?

124

我需要从一个十进制或双精度数中获取左侧整数值,例如:我需要从4.6中获取值4。我尝试使用Math.Floor函数,但它返回的是一个双精度数,例如:它从4.6返回4.0。MSDN文档说它返回一个整数值。我错过了什么吗?或者有没有其他方法可以实现我要找的功能?


3
MSDN文档说明Math.Floor返回System.Double而不是整数。MSDN文档指出该函数返回一个整数值。 - broadband
需要一个整数,但这并不意味着它可以存储在“int”或“long”中。一个“double”可以成功地存储所有整数值,其范围比仅限于“int”的范围要广得多。 请注意,当尾数部分没有足够的位来存储整数值的所有数字时,当其基数2的指数超过52时,某些整数值可能会四舍五入:这种对“double”中整数值的四舍五入可能发生在大于2^52或小于-2^52的整数上,但结果仍将是最接近的可表示整数; 如果使用“(long)Floor(x)”,转换可能会大大错误。 - verdy_p
请注意,“double”类型可以表示的整数值的有效范围非常大,绝对值高达: (1 + (1 − 2^−52)) × 2^1023 ≈ 1.7976931348623157E308;这比“long”类型的2^63-1要大得多。 然而,可以明确存储的整数范围更为有限,因为“double”类型仅具有52位的尾数(加上未存储的最高位隐含的1位),这意味着“double”类型只能精确存储绝对值低于2^53的整数。 - verdy_p
不幸的是,Math.Floor() 不会在内部返回一个变量“Number”类型,如果可能的话,使用“Long”,否则仅用于大型舍入整数的“Double”。标准的 Math 库也无法处理这种统一的变量数字类型。 存在其他实现统一数字类型的数学库,包括 Long、Double 或以打包十进制或二进制编码的大整数,而不会失去支持的范围或精度。 - verdy_p
5个回答

165

double 的取值范围要比 intlong 大得多。看一下这段代码:

double d = 100000000000000000000d;
long x = Math.Floor(d); // Invalid in reality

这个整数超出了long的范围 - 那么你会期望发生什么?

通常情况下,您知道该值实际上会在intlong的范围内,因此需要将其强制转换:

double d = 1000.1234d;
int x = (int) Math.Floor(d);

但是,这种类型转换的责任在于开发人员,而不是Math.Floor本身。让它仅针对long范围之外的所有值失败并抛出异常是没有必要的束缚。


3
Floor函数将浮点数转换为整型返回,对于科学计算它返回一个浮点数。这个答案是不正确的,因为双精度浮点数有64位,长整型也有64位,但是即使双精度浮点数可以在长整型中正确存储,它也不能精确地存储较低有效位的数字。 - Akash Kava
1
@Jon:你为什么没有参与到关于如何在C#中将正数变成负数的激烈辩论中来呢?链接:https://dev59.com/GnM_5IYBdhLWcg3wgzdl - MusiGenesis
3
@Jon:请放心慢慢来。社区发现将正数乘以-1会变成负数,现在StackOverflow上一切都好了。 - MusiGenesis
1
@javapowered:不,(int) 15.0 不是0。其他问题出现了,但仅凭这个无法确定。请创建一个简短但完整的程序来演示此问题,然后提出问题。我怀疑你会发现很难复制... - Jon Skeet
1
@MusiGenesis: <code>(int) IGNORE_RATIO * Volume</code> 被计算为 <code>(int) 0.15 * Volume</code>,但类型转换仅适用于比率,而不是乘积的结果,因此您会得到 <code>0 * Volume</code>,即零! 请改用 <code>(int)(IGNORE_RATIO * Volume)</code> 来解决您的错误。 - verdy_p
显示剩余5条评论

13
根据MSDN文档,Math.Floor(double)返回一个double类型:http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx 如果你需要转换成int类型:
int result = (int)Math.Floor(yourVariable);

我看得出来MSDN文章可能会误导人,他们应该明确指出,虽然结果是一个“整数”(在这种情况下意味着整数),但它仍然是Double类型。


谢谢您的回复。实际上我正在查看这篇文章:http://msdn.microsoft.com/en-us/library/e0b5f0xb.aspx但无论如何,我会尝试您的建议。谢谢。 - Sridhar
虽然在顶部确实写着“返回一个整数”,但下面指定了类型:public static double Floor(double d)。 - Neil N
3
整数不等于int(http://www.answers.com/integer)- 整数可以存储在Double中(请参见Jon的回答),而有无限数量的整数不能存储在int中。 - Shog9
Shog,我并没有说他们不能这样做。我说的是“它仍然是Double类型”。 - Neil N
1
@Neil:没错 - 我只是想强调 “integer”(集合名称)和“int”(类型名称)之间的区别。 - Shog9

4
如果你只需要一个数字的整数部分,将该数字转换为 int 类型即可。这会在小数点处截断数字。
double myDouble = 4.6;
int myInteger = (int)myDouble;

3
需要注意的是,对于负数,将其转换为intFloor的行为不同。 Floor总是截断为最小的负数,而将其转换为int会朝向0进行截断。 - Magnus

-1
Convert.ToInt32(Math.Floor(Convert.ToDouble(value)))

这将给你精确的值,就像如果你取4.6它会返回4作为输出。


-1

Floor将其保留为double,因此您可以对其进行更多的double计算。 如果您想将其作为int使用,请将floor的结果转换为int。 不要将原始double转换为int,因为负数的floor规则与正数不同(如果我没记错的话)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接