获取十进制数的整数部分的最佳方法
Posted
技术标签:
【中文标题】获取十进制数的整数部分的最佳方法【英文标题】:Best way to get whole number part of a Decimal number 【发布时间】:2010-10-03 13:01:48 【问题描述】:返回小数的整数部分的最佳方法是什么(在 c# 中)? (这必须适用于可能不适合 int 的非常大的数字)。
GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324
这样做的目的是:我在数据库中插入一个十进制 (30,4) 字段,并希望确保我不会尝试插入一个对于该字段来说太长的数字。确定小数部分的整数部分的长度是此操作的一部分。
【问题讨论】:
获取不到 int 部分;你可以得到整数部分并放弃小数部分。 Decimal 的整数部分很容易溢出 int 并抛出或环绕,默默地杀死你的代码。 嗯,这就是为什么这个问题不像看起来那么简单。我需要它像处理小数字一样可靠地处理非常大的数字。但是,“整数”比“int”更准确——我将在上面重新表述。 【参考方案1】:希望对你有帮助。
/// <summary>
/// Get the integer part of any decimal number passed trough a string
/// </summary>
/// <param name="decimalNumber">String passed</param>
/// <returns>teh integer part , 0 in case of error</returns>
private int GetIntPart(String decimalNumber)
if(!Decimal.TryParse(decimalNumber, NumberStyles.Any , new CultureInfo("en-US"), out decimal dn))
MessageBox.Show("String " + decimalNumber + " is not in corret format", "GetIntPart", MessageBoxButtons.OK, MessageBoxIcon.Error);
return default(int);
return Convert.ToInt32(Decimal.Truncate(dn));
【讨论】:
【参考方案2】: Public Function getWholeNumber(number As Decimal) As Integer
Dim round = Math.Round(number, 0)
If round > number Then
Return round - 1
Else
Return round
End If
End Function
【讨论】:
接受的答案(八年前发布)解释了为什么这个答案是错误的。decimal
的范围远远大于int
的范围。另外,这不是一个 VB 问题。
@JoeFarrell - 如果您认为答案是错误的,除了留下评论之外,您还可以考虑对其进行否决。但是,不要标记它(不是我说你有)。这是一个回答问题的尝试。它可能是错误的语言,甚至在 VB 中也可能是错误的,但这是一种尝试。例如,请参见“When an answer answers the wrong question, is it Not An Answer?”。【参考方案3】:
分离值及其小数部分值的非常简单的方法。
double d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");
s 是小数部分 = 5 并且 i 是整数 = 3
【讨论】:
见上面的最佳答案。这不起作用,因为(int)Decimal.MaxValue
会溢出。【参考方案4】:
顺便说一句,(int)Decimal.MaxValue 会溢出。您无法获得小数的“int”部分,因为小数太大而无法放入 int 框中。刚刚检查过......它甚至太大了很长一段时间(Int64)。
如果你想要一个 Decimal 值的位到点的 LEFT,你需要这样做:
Math.Truncate(number)
并将值返回为... DECIMAL 或 DOUBLE。
edit:截断绝对是正确的函数!
【讨论】:
所以结果是十进制或双精度,在该点之后永远不会有任何内容,但没有内置对象将结果存储为“int”(没有小数位),看起来有点蹩脚? @CodeBlend:围绕失去精度的愿望设计框架的呼声并不高。 @CodeBlend:您仍然会丢失精度,因为您要截断数字的十进制值。不知道你在做什么。 不确定这是否可行。因为 Math.Truncate(-5.99999999999999999) 为我返回 -6.0...!! @Bharat Mori:似乎 -5.99999999999999999 在截断之前四舍五入到 -6.0。尝试使用后缀“m”,它会起作用。 Math.Truncate(-5.99999999999999999m) 给出 -5。【参考方案5】:我认为System.Math.Truncate 是您正在寻找的。p>
【讨论】:
【参考方案6】:取决于你在做什么。
例如:
//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6
或
//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7
默认始终是前者,这可能会让人感到意外,但makes very good sense。
你的显式演员会做:
int intPart = (int)343564564.5
// intPart will be 343564564
int intPart = (int)343564565.5
// intPart will be 343564566
从你提出问题的方式来看,这听起来不是你想要的——你每次都想把它说出来。
我愿意:
Math.Floor(Math.Abs(number));
还要检查 decimal
的大小 - 它们可能很大,因此您可能需要使用 long
。
【讨论】:
(long)Decimal.MaxValue 溢出。 公平点 - 我想这就是 Math.Truncate(decimal) 返回小数的原因。 在 C# 中,转换为 int 不会四舍五入,因此 (int)0.6f 将为 0,并且 (int)343564565.5 将以 5 结尾,而不是 6。试试这里:repl.it/repls/LuxuriousCheerfulDistributeddatabase跨度> 由于您不能使用 Math.Truncate 的原因,您可能希望使用 Math.Floor 和 Math.Abs,但对于负值,您需要更改符号,例如Math.Floor(Math.Abs(number)) * (number > 0 ? 1 : -1)
。试试dotnetfiddle example【参考方案7】:
你只需要像这样投射它:
int intPart = (int)343564564.4342
如果您仍想在以后的计算中将其用作小数,那么 Math.Truncate(或者如果您想要负数的某种行为,也可能是 Math.Floor)是您想要的函数。
【讨论】:
这是错错错。如果结果大于 Int32 可以容纳的值,它要么抛出异常,要么(甚至更糟!!!)静默溢出并返回,给你一个完全不正确的结果,你甚至都不知道。 不,这不是错。它对非常大的小数/浮点值无效,但在大多数情况下都很好。编码时数字通常被限制为足够低,因此这不是问题。此外,我提供了适用于所有值的 Math.Truncate 解决方案。 我明白你为什么生我的气了。事实是你的答案是错误的。你告诉他要抓住机会不要打破它,因为,嘿,很多数字都很小。这是一个愚蠢的风险。您应该编辑您的答案并删除除 Math.Truncate 之外的所有内容,因为它是唯一正确的部分。 您知道他们对 ASSUME 的评价。另外,你的假设特别糟糕。那是炎症吗?我想你可以这么说。你也可以说,告诉某人做一些愚蠢的事情会导致他们在路上遇到问题,即使不是完全不道德的,也是煽动性的。 如果我打算给出一个误导性的答案,那确实是错误的。事实上,我只是想帮忙。如果我犯了轻微的误解或没有完全理解这个问题,那很公平——这不是犯罪。那我们现在为什么吵架?我们都同意截断是正确的答案。以上是关于获取十进制数的整数部分的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章