Skip to content

5. Rounding

This chapter rounds the strength to a tenth of a megapascal as part of the formula, the way a test method prescribes it. It shows how a rounding names its unit, its places and its mode, and what the mode decides for a value exactly halfway.

The program is chapter 4's first case, with the strength formula rounded, a second rounding that differs only in its mode, and two loads.

Rounding is part of the formula

A test method states its rounding: here, the strength to 0.1 MPa, with a value exactly halfway rounded away from zero. A formula::DecimalRounding names such a rule once: the unit the places are counted in, how many places, and the rounding mode. The program names two rules that differ only in the mode:

constexpr formula::DecimalRounding tenthMpa { unit::Megapascal,
                                              formula::DecimalPlaces { 1 },
                                              formula::RoundingMode::HalfAwayFromZero };
constexpr formula::DecimalRounding tenthMpaHalfEven { unit::Megapascal,
                                                      formula::DecimalPlaces { 1 },
                                                      formula::RoundingMode::HalfEven };

Always name the mode: no single mode is right for every method, so the method's own rule belongs in the declaration. Places count in a unit, because one decimal place of a megapascal and one decimal place of a pascal are different roundings.

formula::rounded<R>(operand) rounds its operand by the rule R, at that position in the formula. The strength formula rounds the quotient:

constexpr auto loadedArea = formula::yields<Area>(var<SideA> * var<SideB>);
constexpr auto strength = formula::yields<Strength>(formula::rounded<tenthMpa>(var<Load> / loadedArea));
constexpr auto strengthHalfEven = formula::yields<Strength>(formula::rounded<tenthMpaHalfEven>(var<Load> / loadedArea));

The quotient is calculated exactly, converted to megapascals, rounded to one place, and the rounded value is the result. A rounding inside a formula is a step of the calculation, unlike the rounding for reading in chapter 3, which only changes the text printed.

The specimen carried 675.4 kN:

auto const specimen = formula::environment(
    formula::Measured<SideA> { 150 }, formula::Measured<SideB> { 150 }, formula::Measured<Load> { 675.4_r });
auto const result = formula::checked_evaluate(strength, specimen);
if (!result)
{
    std::println("cannot calculate the strength: {}", result.error());
    return 1;
}
std::println("675.4 kN, half away from zero: {} = {}", formula::symbol_of<Strength>(), *result);

675.4 kN over 22500 mm² is 30.0177… MPa, which rounds to 30.0. The result is the exact number 30, and prints as 30 MPa: {} writes an exact value without trailing zeros. A format spec that asks for one place in a named mode, {:.1HalfAwayFromZero}, would print 30.0 MPa (Displaying numbers).

The mode matters

A second specimen carried 676.125 kN. Its strength is 30.05 MPa exactly, halfway between 30.0 and 30.1, and the two rules decide it differently:

auto const halfway = formula::environment(
    formula::Measured<SideA> { 150 }, formula::Measured<SideB> { 150 }, formula::Measured<Load> { 676.125_r });
auto const awayFromZero = formula::checked_evaluate(strength, halfway);
if (!awayFromZero)
{
    std::println("cannot calculate the strength: {}", awayFromZero.error());
    return 1;
}
std::println("676.125 kN, half away from zero: {} = {}", formula::symbol_of<Strength>(), *awayFromZero);

auto const toEven = formula::checked_evaluate(strengthHalfEven, halfway);
if (!toEven)
{
    std::println("cannot calculate the strength: {}", toEven.error());
    return 1;
}
std::println("676.125 kN, half to even:        {} = {}", formula::symbol_of<Strength>(), *toEven);

Half away from zero rounds the half up to 30.1. Half to even rounds it to the neighbour whose last digit is even, 30.0. Only a value exactly halfway tells the two modes apart, which is why the mode a method prescribes belongs in its rounding.

Output

675.4 kN, half away from zero: f_c = 30 MPa
676.125 kN, half away from zero: f_c = 30.1 MPa
676.125 kN, half to even:        f_c = 30 MPa

Summary

  • formula::DecimalRounding -- a rounding rule named once: a unit, a number of decimal places and a rounding mode.
  • formula::DecimalPlaces -- how many decimal places of the unit to keep.
  • formula::RoundingMode -- which way to round, including what to do with a value exactly halfway; name the one the method prescribes.
  • formula::rounded<R>(operand) -- rounds the operand by the rule R, at that position in the formula.

Further reading