Arbitrary precision floating point arithmetic library based on PHP's bcmath extension.
npm i @agrora/decimal
TypeScript is supported out of the box. You don't need to install any typings.
;// Create a new decimal from a stringconst decimal = Decimal;// Use add() to add another decimal to itconst sum = decimal;// Log the result as a stringconsole; // "0.3"
Methods can be chained in an immutable way to perform multiple operations at once
const decimal = Decimal;const sum = decimal;console; // "7"const result = sum;console; // "20"console; // "7" (still!)
Decimals can be created from strings, numbers and other decimal-ish objects!
We call all these possible values
DecimalLike in this library.
Decimal;Decimal;Decimal; // Higher than a 64bit unsigned int!Decimal;Decimal;// If you're feeling hackyDecimal;
The Decimal Class
The decimal class acts as a wrapper class around all the functions this library exposes. This is what you want to use for the most part.
The rest of the functions are considered internal for now, but feel free to check out the source code.
The Problem it's trying to solve
To see the problem, open a browser, press F12, go to "Console" and enter the following
>> 0.1 + 0.2
and hit enter. You will notice it will not result in
0.3 as you might've assumed,
but rather in
This is a limitation of how floating point numbers can be represented binary.
Obviously this can lead to huge problems in financial and precision-critical applications.
Most languages solve this problem by having a
float/double implementation as well
decimal implementation. While floats/doubles use the floating point processing
unit of your CPU, decimals are calculated as strings and numbers below our decimal radix (10),
like in typical school maths where you use your hands and carries you remember.
This has two advantages:
- Floating point numbers are calculated precisely and never loose numbers
- Numbers can be bigger than 32 or even 64 bit. In fact, they can be as long as your RAM can store
It also comes at a disadvantage, which is the reason why e.g. graphic applications, games etc. don't worry about precision all too much:
It's expensive. It costs more performance than binary floating point operations. In todays
applications, we don't need to worry about this too much. But before using this library,
try to understand the difference between a
float/double and a
decimal and understand when
to apply which.
If precision is neglectable (e.g. latitude/longitude, geometry, ray casting etc.), rather use a normal number type. For currencies, weights and other precision-critical numbers use a decimal.
Before contributing, check out the Contribution Guidelines
// Pull projectgit clone https://github.com/Agrora/decimal-js// Enter project directorycd decimal-js// Install development dependenciesnpm install// ... make your changes ...// Run testsnpm run test// Lintnpm run lint// Fix linting problemsnpm run lint:fix// Buildnpm run build// ... create branch, commit, push, merge request etc. ...
- Refactoring so that DecimalInfo.length is not needed anymore (based on DecimalInfo.value.length)
- Refactoring of arithmetic methods to reduce cyclomatic complexity
Credits of this library and its algorithms go to:
- tjhei (This search result)
- kvz (This search result)
- The original bcmath author Andy Gutmans (Source Code Credits)
Thank you for your initial work to make this library here possible.