61

This i what I am trying to achieve:

If a double has more than 3 decimal places, I want to truncate any decimal places beyond the third. (do not round.)

Eg.: 12.878999 -> 12.878

If a double has less than 3 decimals, leave unchanged

Eg.:   125   -> 125
       89.24 -> 89.24

I came across this command:

double example = 12.34567;
double output = Math.Round(example, 3);

But I do not want to round. According to the command posted above, 12.34567 -> 12.346

I want to truncate the value so that it becomes: 12.345

Blake Yarbrough
  • 2,286
  • 1
  • 20
  • 36
Ayush
  • 41,754
  • 51
  • 164
  • 239
  • See http://stackoverflow.com/questions/3797342/how-do-i-round-down-a-decimal-to-2-decimal-places-in-net – H H Sep 28 '10 at 15:20

8 Answers8

71

Doubles don't have decimal places - they're not based on decimal digits to start with. You could get "the closest double to the current value when truncated to three decimal digits", but it still wouldn't be exactly the same. You'd be better off using decimal.

Having said that, if it's only the way that rounding happens that's a problem, you can use Math.Truncate(value * 1000) / 1000; which may do what you want. (You don't want rounding at all, by the sounds of it.) It's still potentially "dodgy" though, as the result still won't really just have three decimal places. If you did the same thing with a decimal value, however, it would work:

decimal m = 12.878999m;
m = Math.Truncate(m * 1000m) / 1000m;
Console.WriteLine(m); // 12.878

EDIT: As LBushkin pointed out, you should be clear between truncating for display purposes (which can usually be done in a format specifier) and truncating for further calculations (in which case the above should work).

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 5
    If the "truncation" is only for display purposes, that can be achieved when the value is converted to a string representation. This would preserve precision and avoid some of the pitfalls of trying to perform precise decimal manipulation of a floating point number. – LBushkin Sep 28 '10 at 15:20
  • @LBushkin: True. It depends on what's required. Sometimes businesses really want calculations to be performed on truncated values at each point... and sometimes it's only for display. Good to point out. – Jon Skeet Sep 28 '10 at 15:22
  • @JonSkeet by default it is truncating to 3 decimal places? – Ehsan Sajjad Mar 10 '16 at 13:24
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ: Nope - I'm not sure why you'd think that. – Jon Skeet Mar 10 '16 at 13:25
  • your snippet has no where specified so it made m think' – Ehsan Sajjad Mar 10 '16 at 13:50
  • 1
    @EʜsᴀɴSᴀᴊᴊᴀᴅ: It's multiplying by 1000, truncating to an integer and dividing by 1000. If those were 10000m instead, it would be to 4 decimal places. – Jon Skeet Mar 10 '16 at 14:01
  • for showing specific number percision, this is the recommended way? :http://stackoverflow.com/a/3814295/1875256 – Ehsan Sajjad Mar 10 '16 at 14:04
  • @EʜsᴀɴSᴀᴊᴊᴀᴅ: For *display* purposes, yes, that's fine. – Jon Skeet Mar 10 '16 at 14:05
  • Your statement is wrong, a double has decimal its a floating point type double ±5.0e−324 to ±1.7e308 15-16 digits – Peter Dec 04 '17 at 10:09
  • @user3800527: I think you should read the whole answer. A double is a sign, mantissa and exponent, where the exponent indicates the *binary* shift; it doesn't have *decimal* digits. Yes, that number can be represented in decimal, but that's not inherent data in the value. – Jon Skeet Dec 04 '17 at 10:39
56

I can't think of a reason to explicitly lose precision outside of display purposes. In that case, simply use string formatting.

double example = 12.34567;

Console.Out.WriteLine(example.ToString("#.000"));
Chris Martin
  • 1,871
  • 16
  • 17
  • 5
    I need it because I am matching values from an XML file against those stored in a DB. Both sources are filled in by different parties. The one that fills in the Db chooses not to fill in anything more than 3 decimal places, while the XML file can often have upto 8 decimal places – Ayush Sep 28 '10 at 15:47
  • @StevenSudit And another possible use-case, like mine, is where I have a DB field that can only take 10 chars, but the form has a lb -> kg field where a calculation takes place and can give a number > 10 chars. Sometimes you just want a few significant digits and don't want to truncate or round, but have limitations on how many figures out that you can store. So I would downvote questioning this use-case, as it is very common when storing numbers in a DB field, not upvote it. Luckily it has a useful answer, so I'll upvote, instead. – vapcguy Oct 03 '16 at 15:15
  • ToString rounds the number! – Donny V. Aug 24 '18 at 21:17
25
double example = 3.1416789645;
double output = Convert.ToDouble(example.ToString("N3"));
Merin Nakarmi
  • 3,148
  • 3
  • 35
  • 42
7

Multiply by 1000 then use Truncate then divide by 1000.

Josh
  • 68,005
  • 14
  • 144
  • 156
6

If your purpose in truncating the digits is for display reasons, then you just just use an appropriate formatting when you convert the double to a string.

Methods like String.Format() and Console.WriteLine() (and others) allow you to limit the number of digits of precision a value is formatted with.

Attempting to "truncate" floating point numbers is ill advised - floating point numbers don't have a precise decimal representation in many cases. Applying an approach like scaling the number up, truncating it, and then scaling it down could easily change the value to something quite different from what you'd expected for the "truncated" value.

If you need precise decimal representations of a number you should be using decimal rather than double or float.

LBushkin
  • 129,300
  • 32
  • 216
  • 265
3

You can use:

double example = 12.34567;
double output = ( (double) ( (int) (example * 1000.0) ) ) / 1000.0 ;
Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
  • My only concern here is that conversion to int not only slices the digits after the decimal place but restricts the range of the value to what an int can contain. A double can be much bigger than an int. – Steven Sudit Sep 28 '10 at 15:43
2

Good answers above- if you're looking for something reusable here is the code. Note that you might want to check the decimal places value, and this may overflow.

public static decimal TruncateToDecimalPlace(this decimal numberToTruncate, int decimalPlaces)
{
    decimal power = (decimal)(Math.Pow(10.0, (double)decimalPlaces));

    return Math.Truncate((power * numberToTruncate)) / power;
}
Mike M.
  • 12,343
  • 1
  • 24
  • 28
1

In C lang:

double truncKeepDecimalPlaces(double value, int numDecimals)
{
    int x = pow(10, numDecimals);
    return (double)trunc(value * x) / x;
}
alsantos123
  • 131
  • 1
  • 4