Table of Contents

CalculatedMoney Struct

Definition

Namespace
Bodu.Financial
Assembly
Bodu.Financial.dll
Package
Bodu.Financial 1.0.0
Source
CalculatedMoney.Conversion.cs

Represents a high-precision, runtime-tagged monetary amount whose rounding is deferred until it is converted back to a settlement Money.

public readonly struct CalculatedMoney : IEquatable<CalculatedMoney>
Implements
Inherited Members
Extension Methods

Remarks

CalculatedMoney is the intermediate value used when a chain of monetary calculations must avoid the rounding error that per-step rounding of Money would accumulate - compound interest, unit-rate products, tax apportionment, and similar. Arithmetic preserves the full decimal precision; rounding happens once, at the settlement boundary, through RoundToMoney(MonetaryContext?).

The currency is identified at runtime by CurrencyCode. Arithmetic preserves full precision; rounding to a settlement Money happens at the boundary through RoundToMoney(MonetaryContext?).

CalculatedMoney carries high-precision decimal arithmetic with deferred rounding - it is not an exact rational type. Division such as one-third is held to decimal's 28-29 significant digits, not exactly. When a calculation must be mathematically exact (for example, apportioning by an exact fraction before settlement), use the exact-rational escape hatches on the strongly typed form - FromFraction(Fraction<BigInteger>, MidpointRounding) and MultiplyExact(Fraction<BigInteger>, MidpointRounding) - which compute in Fraction<T> and round once at the settlement boundary. In short: Money/Money<TCurrency> are rounded settlement values, CalculatedMoney is deferred-rounding decimal, and the Fraction APIs are exact rational.

using Bodu.Financial;

// Carry full decimal precision through the calculation chain - no rounding per step.
var principal = new CalculatedMoney(1000m, CurrencyCode.USD);
CalculatedMoney withInterest = principal * 1.0525m * 1.0525m;   // compounded, unrounded

// Round exactly once, at the settlement boundary.
Money settled = withInterest.RoundToMoney();                    // 1,107.76 USD

Constructors

CalculatedMoney(decimal, CurrencyCode)

Initializes a new instance of the CalculatedMoney struct from an amount and currency, preserving the amount's full precision.

public CalculatedMoney(decimal amount, CurrencyCode code)

Parameters

amount decimal

The unrounded monetary amount in the major unit.

code CurrencyCode

The currency identifying this value.

Exceptions

ArgumentOutOfRangeException

code is None or is not a defined CurrencyCode member.

Properties

Amount

Gets the unrounded monetary amount in the major unit of the currency.

public decimal Amount { get; }

Property Value

decimal

The full-precision amount stored by this instance.

Code

Gets the currency identifying this value.

public CurrencyCode Code { get; }

Property Value

CurrencyCode

The stored CurrencyCode, or None for a default-initialised value.

IsZero

Gets a value indicating whether this amount is zero.

public bool IsZero { get; }

Property Value

bool

true when the amount is zero; otherwise false.

Sign

Gets the sign of this amount.

public int Sign { get; }

Property Value

int

-1, 0, or 1.

Methods

Divide(decimal)

Divides this amount by divisor without rounding.

public CalculatedMoney Divide(decimal divisor)

Parameters

divisor decimal

The scalar divisor.

Returns

CalculatedMoney

The full-precision quotient.

Exceptions

DivideByZeroException

divisor is zero.

Equals(CalculatedMoney)

Determines whether this value equals other in both amount and currency.

public bool Equals(CalculatedMoney other)

Parameters

other CalculatedMoney

The value to compare against.

Returns

bool

true when both the amount and currency match; otherwise false.

Equals(object?)

Indicates whether this instance and a specified object are equal.

public override bool Equals(object? obj)

Parameters

obj object

The object to compare with the current instance.

Returns

bool

true if obj and this instance are the same type and represent the same value; otherwise, false.

GetHashCode()

Returns the hash code for this instance.

public override int GetHashCode()

Returns

int

A 32-bit signed integer that is the hash code for this instance.

Multiply(decimal)

Multiplies this amount by multiplier without rounding.

public CalculatedMoney Multiply(decimal multiplier)

Parameters

multiplier decimal

The scalar multiplier.

Returns

CalculatedMoney

The full-precision product.

RoundToMoney(MonetaryContext?)

Materialises this high-precision amount as a settlement Money, rounding according to context.

public Money RoundToMoney(MonetaryContext? context = null)

Parameters

context MonetaryContext

The monetary context governing rounding and scale; null selects Default.

Returns

Money

The settled Money in this value's currency.

Examples

using Bodu.Financial;

var calc = new CalculatedMoney(10m, CurrencyCode.USD).Divide(3m);   // 3.3333... USD, unrounded

Money defaultRule = calc.RoundToMoney();                            // 3.33 USD (banker's rounding)
Money awayFromZero = calc.RoundToMoney(MidpointRounding.AwayFromZero);

Remarks

The scale is resolved from context: CurrencyMinorUnits rounds to the registered currency's minor units and Unrounded falls back to that same natural scale because a settlement value must carry a concrete precision. When the resolved scale differs from the registered minor units (or the currency is unregistered) the result carries the resolved scale explicitly.

Exceptions

InvalidOperationException

This value carries no ISO code (default-initialised).

ArgumentException

context is invalid.

ArgumentOutOfRangeException

context carries an out-of-range policy.

RoundToMoney(MidpointRounding)

Materialises this high-precision amount as a settlement Money, rounding to the currency's minor units using the supplied midpoint rule.

public Money RoundToMoney(MidpointRounding rounding)

Parameters

rounding MidpointRounding

The midpoint-rounding rule applied at the currency's minor-unit precision.

Returns

Money

The settled Money in this value's currency.

Exceptions

InvalidOperationException

This value carries no ISO code (default-initialised).

Operators

operator +(CalculatedMoney, CalculatedMoney)

Adds two high-precision amounts denominated in the same currency, preserving full precision.

public static CalculatedMoney operator +(CalculatedMoney left, CalculatedMoney right)

Parameters

left CalculatedMoney

The first amount.

right CalculatedMoney

The second amount.

Returns

CalculatedMoney

The sum.

Exceptions

InvalidOperationException

The operands have different ISO codes.

operator /(CalculatedMoney, decimal)

Divides a high-precision amount by a scalar without rounding.

public static CalculatedMoney operator /(CalculatedMoney left, decimal right)

Parameters

left CalculatedMoney

The amount.

right decimal

The scalar divisor.

Returns

CalculatedMoney

The full-precision quotient.

Exceptions

DivideByZeroException

right is zero.

operator ==(CalculatedMoney, CalculatedMoney)

Determines whether two values are equal.

public static bool operator ==(CalculatedMoney left, CalculatedMoney right)

Parameters

left CalculatedMoney

The first value.

right CalculatedMoney

The second value.

Returns

bool

true when equal.

operator !=(CalculatedMoney, CalculatedMoney)

Determines whether two values differ.

public static bool operator !=(CalculatedMoney left, CalculatedMoney right)

Parameters

left CalculatedMoney

The first value.

right CalculatedMoney

The second value.

Returns

bool

true when they differ.

operator *(CalculatedMoney, decimal)

Multiplies a high-precision amount by a scalar without rounding.

public static CalculatedMoney operator *(CalculatedMoney left, decimal right)

Parameters

left CalculatedMoney

The amount.

right decimal

The scalar.

Returns

CalculatedMoney

The full-precision product.

operator *(decimal, CalculatedMoney)

Multiplies a scalar by a high-precision amount without rounding.

public static CalculatedMoney operator *(decimal left, CalculatedMoney right)

Parameters

left decimal

The scalar.

right CalculatedMoney

The amount.

Returns

CalculatedMoney

The full-precision product.

operator -(CalculatedMoney, CalculatedMoney)

Subtracts one high-precision amount from another in the same currency, preserving full precision.

public static CalculatedMoney operator -(CalculatedMoney left, CalculatedMoney right)

Parameters

left CalculatedMoney

The minuend.

right CalculatedMoney

The subtrahend.

Returns

CalculatedMoney

The difference.

Exceptions

InvalidOperationException

The operands have different ISO codes.

operator -(CalculatedMoney)

Negates a high-precision amount.

public static CalculatedMoney operator -(CalculatedMoney value)

Parameters

value CalculatedMoney

The amount to negate.

Returns

CalculatedMoney

The negated amount.

operator +(CalculatedMoney)

Returns the operand unchanged.

public static CalculatedMoney operator +(CalculatedMoney value)

Parameters

value CalculatedMoney

The amount.

Returns

CalculatedMoney

The unchanged value.

Applies to

ProductVersions
.NET8, 10