A Java library that abstracts the mathematical operations on real decimal numbers represented in computer memory as
floating-point binary numbers
(Double) or arbitrary-precision
decimal numbers
(BigDecimal).
For build.gradle.kts:
implementation("trade.invision:num:3.0.1")For build.gradle:
implementation 'trade.invision:num:3.0.1'For pom.xml:
<dependency>
<groupId>trade.invision</groupId>
<artifactId>num</artifactId>
<version>3.0.1</version>
</dependency>IEEE 754 floating-point binary numbers
cannot accurately represent
non-integer real decimal numbers in computer memory and FPUs. In
applications that require accurate mathematical operations with non-integer (fractional) decimal numbers, such as
finance programs involving money transactions and currency, using
arbitrary-precision decimal numbers is best practice.
Using floating-point numbers (e.g. float or double) to represent currency can lead to undesirable
inequality calculations,
rounding errors, and
precision loss. Thankfully, Java
provides the BigDecimal
class for working with arbitrary-precision decimal numbers, though it has some
quirks
and doesn't provide many of the functions that the
Math class has for float and
double types. Additionally, mathematical operations on BigDecimal objects can be
significantly slower than the equivalent
mathematical operations on floating-point numbers. This can be problematic in applications such as quantitative finance
and algorithmic trading programs where fast execution time of mathematical operations on currency values is more
desirable and the tradeoff of worse accuracy and lower precision is worth it. Using integer types as a
fixed-point number to represent a currency's minor unit is
another approach, but it can be unintuitive to work with and is still subject to
precision loss. The side effects of using floating-point numbers for
currency may be negligible in certain contexts, such as working with relatively low precision numbers (like stock
prices) or measurements (like technical indicators). So, using floating-point numbers for currency values isn't always
a bad idea. Even Microsoft Excel, a program widely used in finance,
uses floating-point numbers.
You can really go back-and-forth on the tradeoffs between floating-point, fixed-point, and arbitrary-precision numbers.
Enter, the Num interface: an intuitive interface that allows you to focus on using currency values in your application
without constantly worrying about the underlying number representation and easily switch between various number
representations at runtime.
Num, short for "number", is an
interface for performing mathematical operations on real decimal numbers. Implementations wrap a
Number instance so that
performing mathematical operations on floating-point binary numbers
(Double via
DoubleNum) or
arbitrary-precision decimal numbers
(BigDecimal via
DecimalNum) is simple. All
implementations of this interface are interoperable with each other. Operations involving different implementations will
result in a Num that trends towards an increase in precision. For example, subtracting a DecimalNum from a
DoubleNum will result in a DecimalNum. For another example, subtracting a DecimalNum with a context precision of
16 from a DecimalNum with a context precision of 32 will result in a DecimalNum with a context precision of
32. Mathematical operations that result in NaN, +Infinity, -Infinity, or throw an ArithmeticException will
yield a NaNNum.
To get a DoubleNum instance, provide a Number (byte, short, int, long, float, double, BigDecimal),
String, or existing Num to the DoubleNum.doubleNum() static method. Statically importing doubleNum() is
preferred as your code will likely look cleaner.
Getting a DecimalNum instance is similar to DoubleNum, but requires you to specify a precision and rounding mode via
a MathContext. Use
DecimalNum.decimalNum(String, MathContext) or use one of the convenience methods, such as decimalNum64() which
provides approximately the same precision as double, allowing up to 16 significant figures of precision and the same
rounding policy as
double. Again, statically importing decimalNum() is preferred as your code will likely look cleaner.
The NumFactory interface makes
it easy to get Num instances from a given Number, String, or existing Num by simply using NumFactory.of(...)
instead of calling the DoubleNum or DecimalNum static methods directly. To get a NumFactory instance for
DoubleNum, use DoubleNum.FACTORY. To get a NumFactory instance for DecimalNum, use one of the static methods
such as DecimalNum.decimalNum64Factory().
Check out the Javadoc for all classes and method signatures, but here's a quick reference:
For Num:
addsubtractmultiplydivideremainderpowersquarecubeexponentialnthRootsquareRootcubeRootlnlog10log2logabsoluteValuenegatereciprocalincrementdecrementfloorceildegreesradianssincostanasinacosatanatan2sinhcoshtanhasinhacoshatanhhypotenuseaverageminmaxclampintegerPartfractionalPartroundsignificantFiguresmantissaexponentsignumisNegativeisNegativeOrZeroisPositiveisPositiveOrZeroisZeroisEqualisLessThanisLessThanOrEqualisGreaterThanisGreaterThanOrEqualisNaNifNaNifNaNThrowunwraptoBytetoShorttoInttoLongtoFloattoDoubletoBigDecimalgetContextgetContextPrecisiongetContextRoundingModegetFactoryequalshashCodetoString
For NumFactory:
This library's Num interface was inspired by the Num interface of the excellent ta4j
library. There are several improvements and additions that this library's Num interface provides:
- Interoperability between
DoubleNumandDecimalNum - Several more mathematical operations (e.g. trigonometry functions) via
Math in
DoubleNumand via big-math inDecimalNum - No default precision for
DecimalNum(see ta4j issue) - Configurable epsilon for tolerant comparison operations (see
ta4j
DoubleNum) Numberused instead of primitive overloads- Documentation improvements
Big thanks to Eric Obermühlner for the excellent big-math library.
This project is maintained by Invision. Invision enables you to automate and test your investment and trading strategies across billions of data points in seconds using quantitative finance and algorithmic trading programs you build on our code or no-code platform.