获取小数的整数部分的最佳方法


88

返回小数的整数部分(在C#中)的最佳方法是什么?(这必须适用于可能不适合int的非常大的数字)。

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

这样做的目的是:我要在db中插入一个十进制(30,4)字段,并且要确保我不尝试插入一个数字,该数字对于该字段来说太长了。确定小数部分整数的长度是此操作的一部分。


您无法获得int部分;您可以获得整数部分并舍弃小数部分。小数的整数部分很容易溢出int并抛出或环绕,从而无声地杀死了您的代码。

1
好吧,这就是为什么这个问题没有看起来那么简单的原因。我需要这样做才能像处理小数一样可靠地处理非常大的数。但是,“整数”比“整数”更准确-我将在上面重新表述。
Yaakov Ellis

Answers:


211

伙计们,(int)Decimal.MaxValue将溢出。您无法获得小数点的“ int”部分,因为小数点太小而无法放入int框中。刚刚检查过...它甚至太大了(Int64)。

如果要将十进制值的位设置为点的左移,则需要执行以下操作:

Math.Truncate(number)

并将值返回为... DECIMAL或DOUBLE。

编辑:截断绝对是正确的功能!


所以结果是十进制或双精度点,在该点之后将永远没有任何东西,但是没有内置对象将结果存储为似乎有点la脚的“ int”(无小数位)?
合作社

@CodeBlend:围绕失去精确性的需求而设计框架的呼声并不高。

@CodeBlend:您仍然会失去精度,因为您要截取数字的十进制值。不知道你在说什么。

不知道这是否行得通。因为Math.Truncate(-5.99999999999999999)为我返回-6.0 ...!
巴拉特·莫里

@Bharat Mori:似乎-5.999999999999999999999在截断之前四舍五入为-6.0。尝试使用后缀“ m”,它将起作用。Math.Truncate(-5.99999999999999999m)给出-5。
亨利


4

取决于您在做什么。

例如:

//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

默认值始终是前者,这可能会让人感到惊讶,但很有意义

您的显式转换将执行以下操作:

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
sschmidTU

0

您只需要强制转换,如下所示:

int intPart = (int)343564564.4342

如果仍要在以后的计算中将其用作小数,则需要使用Math.Truncate(如果希望对负数有某种行为,则可以使用Math.Floor)。


5
这是错是错,错是错。如果结果大于Int32可以容纳的结果,它将抛出异常或(甚至更糟!)无提示溢出并回绕,从而使您得到一个完全不正确的结果,而您甚至不知道它。

2
不,没错。对于很大的小数/浮点值,许多无效。但是,在大多数情况下,它都很好。在编码时,数字通常被限制为足够低,因此这不必成为问题。另外,我提供了适用于所有值的Math.Truncate解决方案。
Noldorin

2
我明白你为什么生气我。事实是您的答案是错误的。您是在告诉他要抓住机会继续前进,因为嘿,很多数字很小。这是愚蠢的冒险。您应该编辑答案,并删除除Math.Truncate以外的所有内容,因为它是唯一正确的部分。

1
您知道他们对ASSUME的评价。另外,您的假设特别糟糕。那是发炎的吗?我想你可以这么说。您也可以说,告诉某人做一些愚蠢的事情,这将导致他们将来遇到问题,这也是煽动性的,即使这并非毫无道理。

1
的确,如果我打算给出一个误导性的答案,那将是错误的。实际上,我只是在尝试提供帮助。如果我有轻微的误解或不完全理解这个问题,那是很公平的-这不是犯罪。那为什么现在要吵架呢?我们都同意截断是正确的答案。
Noldorin

0

分离值及其分数部分值的非常简单的方法。

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

s是小数部分= 5,
i是整数= 3的值


1
请参阅上方的最佳答案。这不起作用,因为(int)Decimal.MaxValue会溢出。
Yaakov Ellis

0

希望对您有帮助。

/// <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

1
八年前发布的被接受的答案解释了为什么这个答案是错误的。的范围decimal远大于的范围int。另外,这不是VB问题。
乔·法瑞尔

@JoeFarrell-如果您认为答案是错误的,除了对效果发表评论外,您还可以考虑对其进行投票。但是,请不要对其进行标记(不是说我有这个意思)。这是试图回答这个问题的尝试。可能是语言错误,甚至在VB中也可能是错误的,但这是一种尝试。例如,参见“当答案回答错误的问题时,它不是答案吗? ”。
李慧夏
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.