Data and Formats · Lesson 24

Rounding mode and rounding stage

Make numeric presentation rules explicit before aggregating rounded values.

How it works

Rounding is a rule for mapping a value to a chosen precision, and midpoint cases need an explicit tie policy. The sample compares ToEven with AwayFromZero for the decimal value two point three four five. The first produces two point three four; the second produces two point three five.

The next calculation demonstrates a separate decision: when to round. Each half-cent-like decimal becomes one hundredth under the selected rule, so summing individually rounded parts produces two hundredths. Summing the original values first produces one hundredth, which stays one hundredth when rounded. The order of operations changes the result.

Decimal provides base-ten arithmetic suited to many exact decimal quantities, but it does not choose an application's rounding policy. A display format can also round the text it prints without changing the stored value. Keep storage, calculation, rounding, and formatting distinguishable when correctness depends on their boundaries.

Do not repair an unexpected result by adding a tiny arbitrary amount before rounding. That hides a missing policy and can break other inputs, especially negative values and larger magnitudes. Choose the documented mode and stage required by the domain, then test representative midpoint and non-midpoint cases.

Practice with negative two point three four five and with values immediately below and above the midpoint. Predict both modes before running. Add a third small value to the aggregation example and compare rounding each part, rounding a subtotal, and rounding only the final total.

Finally, write a pure calculation function accepting a rounding mode and a clear stage policy, or define separate named functions when the operations mean different things. Tests should assert numeric results independently from formatted strings. The lesson is about reproducible arithmetic behavior; any external business or regulatory rule must be supplied by the actual application's requirements.

A working example

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

Console.WriteLine(Math.Round(2.345m, 2, MidpointRounding.ToEven).ToString("0.00", CultureInfo.InvariantCulture));
Console.WriteLine(Math.Round(2.345m, 2, MidpointRounding.AwayFromZero).ToString("0.00", CultureInfo.InvariantCulture));
decimal[] values = { 0.005m, 0.005m };
decimal roundedParts = values.Sum(value => Math.Round(value, 2, MidpointRounding.AwayFromZero));
decimal roundedTotal = Math.Round(values.Sum(), 2, MidpointRounding.AwayFromZero);
Console.WriteLine(roundedParts.ToString("0.00", CultureInfo.InvariantCulture));
Console.WriteLine(roundedTotal.ToString("0.00", CultureInfo.InvariantCulture));

Expected output

2.34
2.35
0.02
0.01
Try this
Rounding each item and rounding the final sum are different operations.