104

What is the best way to return the whole number part of a decimal (in c#)? (This has to work for very large numbers that may not fit into an int).

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

The purpose of this is: I am inserting into a decimal (30,4) field in the db, and want to ensure that I do not try to insert a number than is too long for the field. Determining the length of the whole number part of the decimal is part of this operation.

2
  • You can't get the int part; you can get the whole number part and ditch the fractional part. The whole number part of a Decimal can easily overflow an int and either throw or wrap around, silently killing your code.
    – user1228
    Commented Jan 26, 2009 at 13:25
  • 1
    Well, that is why this question is not as simple as it seems. I need this to work for very large numbers as reliably as it does for small numbers. However, "whole number" is more accurate than "int" - I will rephrase above. Commented Jan 26, 2009 at 13:32

8 Answers 8

243

By the way guys, (int)Decimal.MaxValue will overflow. You can't get the "int" part of a decimal because the decimal is too friggen big to put in the int box. Just checked... its even too big for a long (Int64).

If you want the bit of a Decimal value to the LEFT of the dot, you need to do this:

Math.Truncate(number)

and return the value as... A DECIMAL or a DOUBLE.

edit: Truncate is definitely the correct function!

7
  • So the result is decimal or double that will never have anything after the point but there is not built in object to store the result as an "int" (without decimal places) that seems a bit lame?
    – Paul C
    Commented May 11, 2014 at 21:48
  • @CodeBlend: There isn't much call for designing frameworks around a desire to lose precision.
    – user1228
    Commented May 12, 2014 at 13:01
  • @CodeBlend: You would still lose precision because you are chopping off the decimal values of a number. Not sure what you're getting at.
    – user1228
    Commented May 12, 2014 at 15:02
  • Not sure this will work or not. Because Math.Truncate(-5.99999999999999999) returns -6.0 for me...!! Commented Oct 19, 2017 at 18:56
  • @Bharat Mori: It seems that -5.99999999999999999 is rounded to -6.0 before the truncate. Try with the suffix "m" and it'll work. Math.Truncate(-5.99999999999999999m) gives -5.
    – Henry
    Commented Feb 23, 2018 at 10:30
28

I think System.Math.Truncate is what you're looking for.

5

Depends on what you're doing.

For instance:

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

or

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

The default is always the former, which can be a surprise but makes very good sense.

Your explicit cast will do:

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

From the way you've worded the question it sounds like this isn't what you want - you want to floor it every time.

I would do:

Math.Floor(Math.Abs(number));

Also check the size of your decimal - they can be quite big, so you may need to use a long.

4
  • (long)Decimal.MaxValue overflows.
    – user1228
    Commented Jan 26, 2009 at 14:12
  • Fair point - I guess that's why Math.Truncate(decimal) returns decimal.
    – Keith
    Commented Jan 26, 2009 at 22:44
  • In C#, casting to int doesn't round, so (int)0.6f will be 0, and (int)343564565.5 will end in 5, not 6. Try here: repl.it/repls/LuxuriousCheerfulDistributeddatabase
    – sschmidTU
    Commented Feb 27, 2020 at 15:11
  • For a reason you can't use Math.Truncate, you might want to go with Math.Floor and Math.Abs but for negative values you need to change sign like Math.Floor(Math.Abs(number)) * (number > 0 ? 1 : -1). Try dotnetfiddle example Commented Jan 15, 2021 at 1:31
1

I hope help you.

/// <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));
}
0

You just need to cast it, as such:

int intPart = (int)343564564.4342

If you still want to use it as a decimal in later calculations, then Math.Truncate (or possibly Math.Floor if you want a certain behaviour for negative numbers) is the function you want.

6
  • 5
    This is wrong wrong wrong. If the result is greater than what an Int32 can hold, it will either throw an exception or (even worse!!!) silently overflow and wrap back around, giving you a completely incorrect result without you even knowing about it.
    – user1228
    Commented Jan 26, 2009 at 13:22
  • 2
    No, it's not wrong. It many not be valid for very large decimals/floating point values, but it is perfectly fine for most situations. Numbers are very often constrained to be low enough when coding, so this need not be a problem. Also, I provided a Math.Truncate solution that works for all values.
    – Noldorin
    Commented Jan 26, 2009 at 13:34
  • 2
    I see why you're pissed at me. The fact is that your answer is wrong. You're telling him to take a chance on it not breaking because, hey, lots of numbers are small. Its a foolish risk to take. You should edit your answer and remove everything but Math.Truncate as its the only correct part.
    – user1228
    Commented Jan 26, 2009 at 18:38
  • 1
    You know what they say about ASSUME. Also, your assumption is particularly awful. Is that inflammatory? I guess you could say that. You can also say that telling somebody to do something foolish that will cause them problems down the road is inflammatory as well, if not flat out unethical.
    – user1228
    Commented Jan 28, 2009 at 15:08
  • 1
    Indeed that would be wrong if I intended to give a misleading answer. As it were, I was simply trying to help. If I am guilty of slightly misunderstanding or not fully appreciating the question, that's fair enough - it's no crime. So why are we arguing now? We all agree Truncate is the right answer.
    – Noldorin
    Commented Jan 29, 2009 at 12:30
0

Very easy way to separate value and its fractional part value.

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

s is fractional part = 5 and
i is value as integer = 3

1
  • 2
    See the top answer above. This doesn't work because (int)Decimal.MaxValue will overflow. Commented Oct 18, 2015 at 23:10
0
   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
2
  • 1
    The accepted answer—posted more than eight years ago—explains why this answer is wrong. The range of decimal is far greater than that of int. Also, this is not a VB question. Commented May 9, 2017 at 15:27
  • @JoeFarrell - if you feel the answer is wrong, you could consider downvoting it in addition to just leaving a comment to the effect. Don't, however, flag it (not that I'm saying you have). It's an attempt to answer the question. It may be in the wrong language, it may be wrong even in VB, but it is an attempt. See, for example, "When an answer answers the wrong question, is it Not An Answer?".
    – Wai Ha Lee
    Commented May 9, 2017 at 21:15
-1

Forgetting the meaning of the term: "Whole Number" seems common in the answers, and in the Question.

Getting the whole number from the number: 4 is simple:

1 x 4 = 4 <- A Whole Number! The first Whole Number!
2 x 4 = 8 <- A Whole Number!
3 x 4 = 12 <- A Whole Number!

Rounding a Number, to get a Whole Number is a cheats method of getting the Whole Numbers! Rounding it removing the Non-Whole Number part of the Number!

1.3 x 4 = 5.2 <- NOT a Whole Number!
1 x 343564564.4342 <- NOT a Whole Number!

Its important to understand what a Whole Number is!

4 / 1 = 4 <- A Whole Number!
4 / 2 = 2 <- A Whole Number!
4 / 3 = 1.333 recurring  <- NOT A Whole Number!

Please ask, and answer the questions with a bit more Accuracy Peeps...

double A = Math.Abs(343564564.4342);
double B = Math.Floor(343564564.4342);
double C = Math.Ceiling(343564564.4342);
double D = Math.Truncate(343564564.4342);

Returns:

A = 343564564.4342
B = 343564564
C = 343564565
D = 343564564

or:

double E = Math.Round(343564564.4342, 0);
E = 343564564

Is a Mathematical Function, thus changing the Number, and not working with Whole Numbers. Your Rounding Non-Whole Numbers!

Not the answer you're looking for? Browse other questions tagged or ask your own question.