UNPKG

exactnumber

Version:

Arbitrary-precision decimals. Enables making math calculations with rational numbers, without precision loss.

203 lines (151 loc) 8.71 kB
import type { Fraction } from './Fraction'; import type { FixedNumber } from './FixedNumber'; // a random, hard to guess number const ROUNDING_MODE_BASE = 201000; export enum RoundingMode { /** Rounds to nearest number, with ties rounded towards +Infinity. Similar to Math.round(). */ NEAREST_TO_POSITIVE = ROUNDING_MODE_BASE + 8, /** Rounds to nearest number, with ties rounded towards -Infinity. */ NEAREST_TO_NEGATIVE = ROUNDING_MODE_BASE + 9, /** Rounds to nearest number, with ties rounded towards the nearest even number. */ NEAREST_TO_EVEN = ROUNDING_MODE_BASE + 10, /** Rounds to nearest number, with ties rounded towards zero. */ NEAREST_TO_ZERO = ROUNDING_MODE_BASE + 11, /** Rounds to nearest number, with ties rounded away from zero. */ NEAREST_AWAY_FROM_ZERO = ROUNDING_MODE_BASE + 12, /** Rounds towards +Infinity. Similar to Math.ceil(). */ TO_POSITIVE = ROUNDING_MODE_BASE + 1, /** Rounds towards -Infinity. Similar to Math.floor(). */ TO_NEGATIVE = ROUNDING_MODE_BASE + 2, /** Rounds towards zero. Similar to Math.trunc(). */ TO_ZERO = ROUNDING_MODE_BASE + 3, /** Rounds away from zero */ AWAY_FROM_ZERO = ROUNDING_MODE_BASE + 4, } export enum ModType { TRUNCATED = 'T', FLOORED = 'F', EUCLIDEAN = 'E', } export interface ExactNumberType { type: 'fraction' | 'fixed'; /** Returns the sum of this number and the given one. */ add(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns the difference of this number and the given one. */ sub(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns the product of this number and the given one. */ mul(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns this number exponentiated to the given value. */ pow(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns modulo of this number exponentiated to the given value (modular exponentiation) */ powm( exponent: number | bigint | string | ExactNumberType, modulus: number | bigint | string | ExactNumberType, type?: ModType, ): ExactNumberType; /** Returns the result of the division of this number by the given one. */ div(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns the result of the integer division of this number by the given one. The fractional part is truncated. */ divToInt(x: number | bigint | string | ExactNumberType): ExactNumberType; mod(x: number | bigint | string | ExactNumberType, type?: ModType): ExactNumberType; /** Returns the absolute value of this number. */ abs(): ExactNumberType; /** Returns the sign of the current value as a number (-1 or 1) */ sign(): -1 | 1; /** Returns the number with inverted sign. (-x) */ neg(): ExactNumberType; /** Returns the inverse of the number. (1/x) */ inv(): ExactNumberType; /** Returns the integer part of the number. */ intPart(): ExactNumberType; /** Returns the fractional part of the number (|res| < 1). */ fracPart(): ExactNumberType; /** Returns true if the number is equal with zero. */ isZero(): boolean; /** Returns true if the number is equal with one. */ isOne(): boolean; /** Returns true if the number does not have a fractional part. */ isInteger(): boolean; /** Returns true if the number is negative. */ isNegative(): boolean; /** Returns the largest number, but less than or equal to the current number. Same as round(RoundingMode.TO_NEGATIVE). */ floor(decimals?: number): ExactNumberType; /** Returns a number which is rounded up to the next largest integer. Same as round(RoundingMode.TO_POSITIVE). */ ceil(decimals?: number): ExactNumberType; /** Truncates the number to the specified number of decimals. Same as round(RoundingMode.TO_ZERO). */ trunc(decimals?: number): ExactNumberType; /** Rounds current number to the specified amount of decimals. * RoundingMode.NEAREST_TO_POSITIVE is the default */ round(decimals?: number, roundingMode?: RoundingMode): ExactNumberType; /** Rounds current number to the specified amount of significant digits. * RoundingMode.NEAREST_TO_POSITIVE is the default */ roundToDigits(digits: number, roundingMode: RoundingMode): ExactNumberType; /** Ensures that number can be represented with specified amount of decimals. * In contrary to round(), this function keeps the repeating decimals in place if cycle length fits into the limit. * RoundingMode.NEAREST_TO_POSITIVE is the default */ limitDecimals(maxDecimals: number, roundingMode?: RoundingMode): ExactNumberType; /** Returns the integer bitwise-and combined with another integer. */ bitwiseAnd(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns the integer bitwise-or combined with another integer. */ bitwiseOr(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns the integer bitwise-xor combined with another integer. */ bitwiseXor(x: number | bigint | string | ExactNumberType): ExactNumberType; /** Returns the integer left shifted by a given number of bits. */ shiftLeft(bitCount: number): ExactNumberType; /** Returns the integer right shifted by a given number of bits. */ shiftRight(bitCount: number): ExactNumberType; /** Compares the current number to the provided number. * Returns -1 when the provided number is smaller than the current one. * Returns 0 when the provided number is equal with the current one. * Returns 1 when the provided number is greater than the current one. */ cmp(x: number | bigint | string | ExactNumberType): -1 | 0 | 1; /** Returns true if the current number is equal to the provided number */ eq(x: number | bigint | string | ExactNumberType): boolean; /** Returns true if the current number is less than the provided number */ lt(x: number | bigint | string | ExactNumberType): boolean; /** Returns true if the current number is less than or equal to the provided number */ lte(x: number | bigint | string | ExactNumberType): boolean; /** Returns true if the current number is greater than the provided number */ gt(x: number | bigint | string | ExactNumberType): boolean; /** Returns true if the current number is greater than or equal to the provided number */ gte(x: number | bigint | string | ExactNumberType): boolean; /** Returns number which is clamped to the range delineated by min and max. */ clamp( min: number | bigint | string | ExactNumberType, max: number | bigint | string | ExactNumberType, ): ExactNumberType; /** Returns the numerator and the denominator of the current number. * By default it simplifies the fraction */ getFractionParts(normalize?: boolean): { numerator: ExactNumberType; denominator: ExactNumberType }; /** Returns opimized internal representation of the current number (e.g. it simplifies fractions using GCD) * This is may be a slow operation, but in some cases normalization might help with performance of repeated operations. */ normalize(): ExactNumberType; /** Returns a string representing the number using fixed-point notation, rounded to the specified number of decimals. * Defaults to RoundingMode.TO_ZERO */ toFixed(decimals: number, roundingMode?: RoundingMode, trimZeros?: boolean): string; /** Returns a string representing the number in exponential notation. * Defaults to RoundingMode.TO_ZERO */ toExponential(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string; /** Returns a string representing the number using fixed-point notation, rounded to the specified number of significant digits. * In contrary to JS Number.toPrecision(), this function never returns exponential notation. * Defaults to RoundingMode.TO_ZERO */ toPrecision(digits: number, roundingMode?: RoundingMode, trimZeros?: boolean): string; /** Converts current value to a JavaScript Number */ toNumber(): number; /** Returns string representation of the current number in a fractional format like "1/2". It always simplifies the fraction before output. */ toFraction(): string; /** Returns string representation in decimal format. * The result might contain repeating digit sequences formatted like "1.4(3)" * It is recommended to set a maximum length for the fractional part to avoid performance issues when having long cycles. * When such limit is provided, toString() truncates the undesired digits */ toString(radix?: number, maxDigits?: number): string; } export type CommonNumberFields = FixedNumber | Fraction; export type ExactNumberParameter = number | bigint | string | ExactNumberType;