Working with NumericValueAsString
All numeric results are NumericValueAsString value objects backed by a precise bcmath string. Build one with the ::of() named constructor — cleaner than new:
use RoundlyConsulting\TradingAnalytics\DataTransferObjects\NumericValueAsString;
NumericValueAsString::of('1.005')->round(2)->toRawString(); // '1.01' — half away from zero
NumericValueAsString::of('1.005', scale: 2)->toRawString(); // '1.00' — the scale truncates
NumericValueAsString::of('1e-5')->toRawString(); // '0.0000100000'
NumericValueAsString::of(0.00001)->toRawString(); // '0.0000100000' — floats expand exactly
$value = NumericValueAsString::of('21', scale: 2);
(string) $value->withSuffix('USD'); // '21.00 USD'
$value->toFloat(); // 21.0, when you explicitly want a float
$value->toInt(); // 21Input is read exactly: numeric strings (padding allowed), integers, floats and exponent notation ('1.5e-3', 0.00001) are expanded into plain decimals before bcmath sees them.
Arithmetic and mutability
add(), subtract(), multiply(), divide(), pow() and abs() change the value in place and return it, so they chain. Pass immutable: true to get a new instance instead — do that when you compute with the engine’s results, so the results themselves stay untouched:
$a = NumericValueAsString::of('10.50', scale: 2);
$a->add(1)->subtract('0.5')->multiply(2); // mutates $a in place and chains
$a->toRawString(); // '22.00'
$b = $a->divide(4, immutable: true); // a new instance; $a is unchanged
$b->toRawString(); // '5.50'
$a->pow(2, immutable: true); // '484.00' — integer exponents only
NumericValueAsString::of('-3.25', scale: 2)->abs()->toRawString(); // '3.25'round($scale) rounds half away from zero (bcmath itself only truncates) and switches the value to the new scale.
Comparisons
$v = NumericValueAsString::of('0.75', scale: 4);
$v->isGreaterThan('0.5'); // true
$v->isLessThanOrEqualTo(1); // true
$v->equals('0.7500'); // true
$v->isZero(); // false
$v->isPositiveNonZero(); // trueisGreaterThanOrEqualTo(), isLessThan() and isNonZero() complete the set. Every comparison accepts a string, int, float or another NumericValueAsString.
Display formatting
Format a result for display without mutating the stored value using the immutable withPrefix() / withSuffix() helpers, which return a new instance. toString() (and a (string) cast) joins prefix, value and suffix with spaces; toRawString() is always the bare number:
$fees = $analytics->commission->global->total->total;
$fees->withSuffix('USD')->toString(); // '19.00 USD' — a new instance
$fees->withPrefix('Fees:')->toString(); // 'Fees: 19.00'
$fees->toString(); // '19.00' — the original is unchanged
$fees->toArray();
// ['value' => '19.00', 'scale' => 2, 'prefix' => '', 'suffix' => '', 'formatted' => '19.00']Which figures follow the run’s scale and which have a fixed one is listed under Precision.
Reference
- of($value, scale: 10, prefix: '', suffix: '') — named constructor; new NumericValueAsString(...) accepts the same named arguments.
- set($value, ?scale) — replace the value; scale() / getScale() — change or read the scale.
- clone() / cloneWithScale($scale) — copies of the value, without prefix or suffix.
- wasChanged() — whether the value was last changed by an arithmetic operation.
- toString(), toRawString(), toInt(), toFloat(), toArray(), toJson().
Dividing by zero throws DivisionByZeroException; non-numeric input ('abc', INF, NAN), an exponent above 1000 or a fractional pow() exponent throws InvalidNumericOperationException; a negative scale throws InvalidScaleException.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.