CodeGym /Courses /C# SELF /Rounding Floating Point Types

Rounding Floating Point Types

C# SELF
Level 6 , Lesson 4
Available

1. Intro

In real life, it's pretty rare to pay money down to a hundred-trillionth of a euro, or measure a room to the hundredth of a millimeter. Same goes for programming: results with double or float are often just “way too fractional.”

Here's a classic problem:

double result = 10.0 / 3.0;
Console.WriteLine(result); // 3.3333333333333335
Floating point division — result with a "tail"

But what if we want to print this number, say, with just two decimal places (so we don't “scare” the user)? That's where rounding comes in.

2. Main Rounding Methods in C#

C# gives you a few ways to round a floating point number. And here's where it gets interesting: there are different kinds of rounding! Let's check out the main options and see how they're different.

1) Math.Round — Classic Rounding

The most popular way is the Math.Round method. It rounds a number to the nearest integer (or to however many decimal places you want).


Math.Round(number[, decimal_places[, MidpointRounding]])
Math.Round syntax
  • number — what you're rounding.
  • decimal_places — how many decimal places to keep (default is 0, so just to an integer).
  • MidpointRounding — the rounding method for halves (we'll talk about this soon).

Examples:

double x = 2.71828;

Console.WriteLine(Math.Round(x));         // 3
Console.WriteLine(Math.Round(x, 2));      // 2.72
Console.WriteLine(Math.Round(x, 3));      // 2.718

Visualization:

Input Value Math.Round(x) Math.Round(x, 2)
2.3 2 2.3
2.5 2 2.5
2.7 3 2.7
2.71828 3 2.72

Result type:
All the functions in this lecture return double, so if you want to assign the rounded result, you might get an error:

double result = 10.0 / 5.0;     // Result is 2.0
int x = Math.Round(x);          // Error! You can't just assign a double to an int variable

If you want to assign a double to an int variable, you need to cast it explicitly:

double result = 10.0 / 5.0;     // Result is 2.0
int x = (int) Math.Round(x);    // Works just fine!

2) Rounding Up or Down

C# supports not just “classic” rounding, but also forced rounding up or down.

Rounding Down (Math.Floor)

The Math.Floor method just “chops off” the decimal part (towards minus infinity). So it always rounds down!

Console.WriteLine(Math.Floor(2.99));   // 2
Console.WriteLine(Math.Floor(-2.99));  // -3

Rounding Up (Math.Ceiling)

The Math.Ceiling method is the opposite of Floor: it always rounds up (towards plus infinity).

Console.WriteLine(Math.Ceiling(2.01));   // 3
Console.WriteLine(Math.Ceiling(-2.01));  // -2

Comparison chart:

Function 2.3 -2.3
Math.Round 2 -2
Math.Floor 2 -3
Math.Ceiling 3 -2

3) Truncate: Just Chop Off the Decimal Part

The Math.Truncate method is like a “chill surgeon.” It just removes the decimal part, not caring about mathematical correctness in terms of rounding. If x is positive — result is like Floor, if negative — like Ceiling.

Console.WriteLine(Math.Truncate(2.99));   // 2
Console.WriteLine(Math.Truncate(-2.99));  // -2

3. How Does Math.Round Work for “Halves”? (MidpointRounding)

Imagine you have 2.5. Which way do you round? It's smack in the middle between 2 and 3. In math, there are two popular approaches:

  • Round up (“to the next bigger one”)
  • Round to the nearest even (Banker's rounding)

C# by default uses the second approach — round to the nearest even (“banker's rounding”).

Console.WriteLine(Math.Round(2.5)); // 2
Console.WriteLine(Math.Round(3.5)); // 4

Why? Because out of two equally close integers, the even one “wins.” This is done so that when you do a lot of rounding, you don't get a systematic error up or down. This is super important, for example, when calculating big sums of money in a bank (hence the name).

If you want to always round up, you can explicitly set the mode:

// Always round "away from zero"
Console.WriteLine(Math.Round(2.5, 0, MidpointRounding.AwayFromZero)); // 3
Console.WriteLine(Math.Round(-2.5, 0, MidpointRounding.AwayFromZero)); // -3

MidpointRounding modes table:

Input Value Round (Default) AwayFromZero ToZero / ToEven
2.5 2 3 2
3.5 4 4 4
-2.5 -2 -3 -2

4. Rounding to a Certain Number of Digits: Don't Forget About "Eights" and "Threes"!

Sometimes you need to round not to an integer, but, say, to two decimal places (like for money or percentages).

double price = 149.9999;
double roundedPrice = Math.Round(price, 2);
Console.WriteLine(roundedPrice); // 150

What if we just want to “chop off” extra digits, but not round? For example, turn 123.4567 into 123.45.

You can do this with a little trick:

double num = 123.4567;
double result = Math.Floor(num * 100) / 100;
Console.WriteLine(result); // 123.45

We're manually “shifting” the decimal point, chopping off the decimal part, and shifting it back.

5. Output Formatting vs Rounding

IMPORTANT!

Output formatting ({x:F2}) — isn't always "real" rounding, it's just a “mask” for how the number looks on the screen. In memory, it's still the long “tailed” double. If you actually need to round and save the value, use Math.Round.

Here's an example where the difference can really matter:

double value = 2.555;
Console.WriteLine($"{value:F2}"); // 2.56
Console.WriteLine(Math.Round(value, 2)); // 2.56

double stored = Math.Round(value, 2);
Console.WriteLine(stored); // 2.56

// But if you just print without rounding, but with formatting...
Console.WriteLine($"{value:F2}"); // 2.56, but in memory — 2.555

6. Typical Mistakes and Gotchas

  • Don't use rounding for precise financial calculations with double! For money in .NET there's a special type decimal — it doesn't “mess around” with floating point (more on this in another lecture).
  • Sad “stuck eights”: because of binary storage, not all numbers round “logically” to the eye. For example, 0.1 + 0.2 might not be 0.3 at all.
  • Don't mix up Math.Floor and Math.Round! The first always goes down, the second — does what math says.
  • Uncontrolled error accumulation: if you keep rounding calculation results along the way (like inside a loop), the final value might “drift” unexpectedly. Usually it's better to round only the final result, not every intermediate step.

7. Final Table: What Does Each Method Give?

Input Value Math.Round(x) Math.Floor(x) Math.Ceiling(x) Math.Truncate(x)
3.2 3 3 4 3
3.5 4 3 4 3
-3.2 -3 -4 -3 -3
-3.5 -4 -4 -3 -3

8. Fun Facts

  • Once, NASA lost a spacecraft because of sloppy rounding of coordinates and a mix-up between metric/imperial units. Moral: round consciously!
  • Banks switched to “banker's rounding” a long time ago so they wouldn't lose pennies — back in the day, everyone just rounded up, and clients lost fractions of a cent on every transfer.
  • C# even has a Math.Sign method that returns the sign of a number — sometimes handy before rounding, so you can decide yourself which way to “chop.”
2
Task
C# SELF, level 6, lesson 4
Locked
Rounding to a specified number of decimal places
Rounding to a specified number of decimal places
2
Task
C# SELF, level 6, lesson 4
Locked
Using Different Rounding Methods
Using Different Rounding Methods
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION