diff --git a/BigDecimal.js b/BigDecimal.js index dba64b6..8d69386 100644 --- a/BigDecimal.js +++ b/BigDecimal.js @@ -1,4 +1,4 @@ -/*jslint bigint: true, vars: true, indent: 2*/ +/*jslint bigint: true, vars: true, indent: 2, esversion:11*/ // https://github.com/tc39/proposal-decimal // https://en.wikipedia.org/wiki/Floating-point_arithmetic @@ -23,20 +23,6 @@ // a.toPrecision(precision[, roundingMode = "half-up"]) // a.toExponential(fractionDigits[, roundingMode = "half-up"]) -// Math: (not in the spec) -// BigDecimal.log(a, rounding) -// BigDecimal.exp(a, rounding) -// BigDecimal.sin(a, rounding) -// BigDecimal.cos(a, rounding) -// BigDecimal.atan(a, rounding) -// BigDecimal.sqrt(a, rounding) - -// "simple" Math functions: -// BigDecimal.abs(a) -// BigDecimal.sign(a) -// BigDecimal.max(a, b) -// BigDecimal.min(a, b) - // (!) Note: consider to use only "half-even" rounding mode and rounding to a maximum number of significant digits for floating-point arithmetic, // or only "floor" rounding to a maximum number of fraction digits for fixed-point arithmetic. // BigFloat may have better performance. @@ -51,6 +37,11 @@ const factory = function (BASE, format = null) { const defaultRounding = format === 'decimal128' ? {maximumFractionDigits: 6176, maximumSignificantDigits: 34, roundingMode: 'half-even'} : null; +function getExponent(number) { + const e = Math.floor(Math.log(Math.abs(number)) / Math.log(2)) - 1; + return Math.abs(number) / 2**e >= 2 ? e + 1 : e; +} + function convert(value) { if (value instanceof BigDecimal) { return value; @@ -154,6 +145,21 @@ const toBigInt = function (a) { } return bigIntScale(a.significand, exponent); }; + +const abs = function (a) { + return a.significand < 0n ? BigDecimal.unaryMinus(a) : a; +}; + +function getCountOfDigits(a) { // floor(log(abs(a))/log(BASE)) + 1 + if (a.significand === 0n) { + throw new RangeError(); + } + return BigInt(digits(a.significand)) + BigInt(a.exponent); +} +function exponentiateBase(n) { + return create(BASE, n); +} + function create(significand, exponent) { return /*Object.freeze(*/new BigDecimal(significand, exponent)/*)*/; } @@ -705,13 +711,13 @@ BigDecimal.prototype.toFixed = function (fractionDigits, roundingMode = "half-up const value = BASE === 10 ? create(this.significand, sum(this.exponent, fractionDigits)) : BigDecimal.multiply(convert(10n**BigInt(fractionDigits)), this); const sign = value.significand < 0n ? "-" : ""; const rounded = BigDecimal.round(value, {maximumFractionDigits: 0, roundingMode: roundingMode}); - const a = BigDecimal.abs(rounded); + const a = abs(rounded); return sign + toFixed(toBigInt(a).toString(), 0 - fractionDigits, fractionDigits); }; function getDecimalSignificantAndExponent(value, precision, roundingMode) { if (BASE === 10) { - const x = BigDecimal.round(BigDecimal.abs(value), {maximumSignificantDigits: precision, roundingMode: roundingMode}); + const x = BigDecimal.round(abs(value), {maximumSignificantDigits: precision, roundingMode: roundingMode}); return {significand: x.significand.toString(), exponent: BigInt(x.exponent)}; } //TODO: fix performance, test @@ -759,7 +765,7 @@ function getDecimalSignificantAndExponent(value, precision, roundingMode) { let result = undefined; let fd = 0n; do { - let x = BigDecimal.abs(value); + let x = abs(value); fd = 0n - logarithm(x, 10, rounding); x = BigDecimal.multiply(exponentiate(ten, fd, rounding), x, rounding); if (BigDecimal.cmp(x, ten) >= 0) { @@ -774,15 +780,15 @@ function getDecimalSignificantAndExponent(value, precision, roundingMode) { fd += BigInt(precision - 1); //TODO: ? if (rounding.maximumSignificantDigits > (Math.abs(Number(fd)) + precision) * Math.log2(10) + digits(value.significand)) { - x = BigDecimal.abs(value); + x = abs(value); x = BigDecimal.multiply(x, exponentiate(ten, fd, rounding), rounding) - result = toBigInt(BigDecimal.abs(roundToInteger(x))).toString(); + result = toBigInt(abs(roundToInteger(x))).toString(); } else { x = BigDecimal.multiply(x, exponentiate(ten, BigInt(precision - 1), rounding), rounding); - x = BigDecimal.abs(x); - const error = BigDecimal.multiply(BigDecimal.multiply(convert(bigIntAbs(fd) + BigInt(precision)), exponentiateBase(BASE, 0 - rounding.maximumSignificantDigits)), x); + x = abs(x); + const error = BigDecimal.multiply(BigDecimal.multiply(convert(bigIntAbs(fd) + BigInt(precision)), exponentiateBase(0 - rounding.maximumSignificantDigits)), x); if (BigDecimal.cmp(roundToInteger(BigDecimal.add(x, error)), roundToInteger(BigDecimal.subtract(x, error))) === 0) { - result = toBigInt(BigDecimal.abs(roundToInteger(x))).toString(); + result = toBigInt(abs(roundToInteger(x))).toString(); } } } diff --git a/BigDecimalMath.js b/BigDecimalMath.js index 485b328..b0c7664 100644 --- a/BigDecimalMath.js +++ b/BigDecimalMath.js @@ -1,19 +1,146 @@ /*jshint esversion:11*/ +// Math: (not in the spec) +// BigDecimal.log(a, rounding) +// BigDecimal.exp(a, rounding) +// BigDecimal.sin(a, rounding) +// BigDecimal.cos(a, rounding) +// BigDecimal.atan(a, rounding) +// BigDecimal.sqrt(a, rounding) + +// "simple" Math functions: +// BigDecimal.abs(a) +// BigDecimal.sign(a) +// BigDecimal.max(a, b) +// BigDecimal.min(a, b) + function addMath(BigDecimal, BASE) { const BASE_LOG2_INV = 1 / Math.log2(BASE); + const BIGINT_BASE = BigInt(BASE); + +function convert(x) { + return BigDecimal(x); +} + + //TODO: REMOVE(?) + const exponentiate = function (x, n) { + if (n < 0n) { + return BigDecimal.divide(convert(1), exponentiate(x, -BigInt(n))); + } + let y = undefined; + while (n >= 1n) { + if (n % 2n === 0n) { + x = BigDecimal.multiply(x, x); + n /= 2n; + } else { + y = y == undefined ? x : BigDecimal.multiply(x, y); + n -= 1n; + } + } + return y == undefined ? convert(1) : y; + }; + +function exponentiateBase(n) { + //TODO: !? + //return create(1n, n); + return exponentiate(convert(BASE), BigInt(n)); +} + +function bigIntAbs(a) { + return a < 0n ? 0n - a : a; +} + + const NumberSafeBits = Math.floor(Math.log2(Number.MAX_SAFE_INTEGER + 1)); + +function bitLength(a) { + const s = a.toString(16); + const c = +s.charCodeAt(0) - "0".charCodeAt(0); + if (c <= 0) { + throw new RangeError(); + } + return (s.length - 1) * 4 + (32 - Math.clz32(Math.min(c, 8))); +} -function exponentiate(a, n) { - if (+a !== BASE) { - throw new RangeError("a should be BASE");//? +function bigIntLog2(n) { + const k = bitLength(n) - NumberSafeBits; + const leadingDigits = Number(n >> BigInt(k)); + return Math.log2(leadingDigits) + k; +} + +//TODO: REMOVE(?) +function digits(a) { // floor(log(abs(a)) / log(BASE)) + 1 + a = bigIntAbs(a); + if (BASE === 2) { + return bitLength(a); + } + const number = Number(BigInt(a)); + if (number < (Number.MAX_SAFE_INTEGER + 1) / 16) { + return Math.floor(Math.log2(number + 0.5) * BASE_LOG2_INV) + 1; + } + const e = (number < 1 / 0 ? Math.log2(number) : bigIntLog2(a)) * BASE_LOG2_INV; + if (Math.floor(e * (1 - 32 / (Number.MAX_SAFE_INTEGER + 1))) === Math.floor(e) && + Math.floor(e * (1 + 32 / (Number.MAX_SAFE_INTEGER + 1))) === Math.floor(e)) { + return Math.floor(e) + 1; + } + const i = Math.floor(e + 0.5); + return a >= BigInt(cachedPower(i)) ? i + 1 : i; +} + +function cachedFunction(f) { + let cache = {}; + let cacheSize = 0; + return function (k) { + let lastValue = cache[k]; + if (lastValue == null) { + if (cacheSize > 100) { + cache = {}; + cacheSize = 0; + } + lastValue = f(k); + cache[k] = lastValue; + cacheSize += 1; + } + return lastValue; + }; +} +const cachedBigInt = cachedFunction(function (k) { + // k === maximumFractionDigits + return BigInt(k); +}); +const cachedPower = cachedFunction(function (k) { + return BIGINT_BASE**BigInt(k); +}); + +function bigIntScale(a, scaling) { + if (typeof a !== 'bigint') { + throw new TypeError(); } - return create(1n, n); + return (BASE === 2 ? (a << cachedBigInt(scaling)) : cachedPower(scaling) * a); } -function exponentiateBase(a, n) { - return exponentiate(a, n); +function bigIntUnscale(a, unscaling) { + if (typeof a !== 'bigint') { + throw new TypeError(); + } + return (BASE === 2 ? (a >> cachedBigInt(unscaling)) : a / cachedPower(unscaling)); } +//TODO: remove +const toBigInt = function (a) { + const e = a.exponent; + const exponent = typeof e === 'number' ? e : Number(BigInt(e)); + if (exponent === 0) { + return a.significand; + } + if (exponent < 0) { + const result = bigIntUnscale(a.significand, 0 - exponent); + if (bigIntScale(result, 0 - exponent) !== BigInt(a.significand)) { + throw new RangeError("The BigDecimal " + a.toString() + " cannot be converted to a BigInt because it is not an integer"); + } + return result; + } + return bigIntScale(a.significand, exponent); +}; function getCountOfDigits(a) { // floor(log(abs(a))/log(BASE)) + 1 if (a.significand === 0n) { @@ -59,10 +186,6 @@ function significandDigits(a) { return to; } -function getExponent(number) { - const e = Math.floor(Math.log(Math.abs(number)) / Math.log(2)) - 1; - return Math.abs(number) / 2**e >= 2 ? e + 1 : e; -} @@ -118,7 +241,7 @@ function tryToMakeCorrectlyRounded(specialValue, f, name) { result = f(x, internalRounding); } // round(result - error) === round(result + error) - error = BigDecimal.multiply(exponentiate(BASE, -BigInt(internalRounding.maximumSignificantDigits)), BigDecimal.abs(result)); + error = BigDecimal.multiply(exponentiateBase(-BigInt(internalRounding.maximumSignificantDigits)), BigDecimal.abs(result)); //if (i > 0) { //console.log(i, f.name, x + "", result + "", error + "", BigDecimal.round(BigDecimal.subtract(result, error), rounding) + "", BigDecimal.round(BigDecimal.add(result, error), rounding) + ""); //} @@ -153,15 +276,15 @@ BigDecimal.log = tryToMakeCorrectlyRounded(1, function log(x, rounding) { if (true) { //! ln(f * BASE**k) = ln(f) + k * ln(BASE), where (1/BASE) <= f <= BASE let k = getCountOfDigits(x) - 1n; - let f = BigDecimal.multiply(exponentiate(BASE, -k), x); + let f = BigDecimal.multiply(exponentiateBase(-k), x); let ff = BigDecimal.round(BigDecimal.multiply(f, f), {maximumSignificantDigits: 3, roundingMode: "half-even"}); - if (BigDecimal.cmp(ff, exponentiate(BASE, 1n)) > 0) { + if (BigDecimal.cmp(ff, exponentiateBase(1n)) > 0) { k += 1n; - f = BigDecimal.multiply(exponentiate(BASE, -1n), f); + f = BigDecimal.multiply(exponentiateBase(-1n), f); } - if (BigDecimal.cmp(ff, exponentiate(BASE, -1n)) < 0) { + if (BigDecimal.cmp(ff, exponentiateBase(-1n)) < 0) { k -= 1n; - f = BigDecimal.multiply(exponentiate(BASE, 1n), f); + f = BigDecimal.multiply(exponentiateBase(1n), f); } if (k !== 0n) { return BigDecimal.add(BigDecimal.log(f, internalRounding), BigDecimal.multiply(convert(2n * k), BigDecimal.log(sqrt(convert(BASE), internalRounding), internalRounding))); @@ -206,7 +329,7 @@ BigDecimal.exp = tryToMakeCorrectlyRounded(0, function exp(x, rounding) { const k = BigDecimal.round(BigDecimal.divide(x, logBASE, {maximumSignificantDigits: Math.max(Number(getCountOfDigits(x)), 1), roundingMode: "half-even"}), {maximumFractionDigits: 0, roundingMode: "half-even"}); if (BigDecimal.cmp(k, convert(0)) !== 0) { const r = BigDecimal.subtract(x, BigDecimal.multiply(k, logBASE)); - return BigDecimal.multiply(exponentiate(BASE, toBigInt(k)), BigDecimal.exp(r, internalRounding)); + return BigDecimal.multiply(exponentiateBase(toBigInt(k)), BigDecimal.exp(r, internalRounding)); } } } @@ -317,14 +440,14 @@ BigDecimal.sqrt = function (x, rounding) { } // https://en.wikipedia.org/wiki/Nth_root#Using_Newton's_method const e = getCountOfDigits(x) / 2n; - const t = exponentiate(BASE, e); - const y = BigDecimal.multiply(x, exponentiate(BASE, -(2n * e))); + const t = exponentiateBase(e); + const y = BigDecimal.multiply(x, exponentiateBase(-(2n * e))); const k = Math.floor(Math.log2(Number.MAX_SAFE_INTEGER + 1) * BASE_LOG2_INV) - 1; - const xn = Number(toBigInt(BigDecimal.round(BigDecimal.multiply(y, exponentiate(BASE, k)), {maximumFractionDigits: 0, roundingMode: "half-even"}))) / BASE**k; + const xn = Number(toBigInt(BigDecimal.round(BigDecimal.multiply(y, exponentiateBase(k)), {maximumFractionDigits: 0, roundingMode: "half-even"}))) / BASE**k; const r = Math.sqrt(xn); //TODO: fix const resultSignificantDigits = 2 * (rounding.maximumSignificantDigits || (rounding.maximumFractionDigits + Math.ceil(significandDigits(x) / 2)) || 1); - let result = BigDecimal.multiply(convert(Math.sign(r) * Math.floor(Math.abs(r) * BASE**k + 0.5)), exponentiate(BASE, -k)); + let result = BigDecimal.multiply(convert(Math.sign(r) * Math.floor(Math.abs(r) * BASE**k + 0.5)), exponentiateBase(-k)); const iteration = function (result, internalRounding) { return BigDecimal.divide(BigDecimal.add(y, BigDecimal.multiply(result, result)), BigDecimal.multiply(convert(2), result), internalRounding); }; @@ -338,3 +461,4 @@ BigDecimal.sqrt = function (x, rounding) { } +export default addMath; \ No newline at end of file diff --git a/README.md b/README.md index 2f3eb65..843ca14 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ It can be compiled using https://www.npmjs.com/package/babel-plugin-transform-bi BigDecimal.cmp(a, b) ## Math: (not in the spec) + To use: + import addMath from './BigDecimalMath.js'; + addMath(BigDecimal, 10); BigDecimal.abs(a) BigDecimal.sign(a) diff --git a/tests.js b/tests.js index 064f9e7..7820f9f 100644 --- a/tests.js +++ b/tests.js @@ -1,6 +1,9 @@ import BigDecimal2 from './BigDecimalByDecimal.js.js'; import {BigDecimal, BigFloat, Decimal128} from './BigDecimal.js'; +import addMath from './BigDecimalMath.js'; +addMath(BigDecimal, 10); +addMath(BigFloat, 2); console.assert(Decimal128('3').toString() === '3'); @@ -202,9 +205,6 @@ console.assert(BigDecimal.add(BigDecimal.BigDecimal('1e+9000000000000000'), BigD // console.time(); exponentiate(BigDecimal.BigDecimal(10), 1000000n); console.timeEnd(); //console.assert(BigDecimal.divide(BigDecimal.BigDecimal(1), BigDecimal.BigDecimal(10), {maximumSignificantDigits: 1e9, roundingMode: 'half-even'}).toString() === '0.1'); // performance //console.assert(BigDecimal.divide(BigDecimal.BigDecimal(1), BigDecimal.BigDecimal(10), {maximumFractionDigits: 1e15}).toString(), '?'); // performance -//console.assert(BigDecimal.exp(BigDecimal.BigDecimal('1e+100'), { maximumSignificantDigits: 1, roundingMode: 'half-even' }).toString() === '2e+4342944819032518276511289189166050822943970058036665661144537831658646492088707747292249493384317483'); -//console.assert(BigDecimal.exp(BigDecimal.BigDecimal('-1e+100'), { maximumSignificantDigits: 1, roundingMode: 'half-even' }).toString() === '7e-4342944819032518276511289189166050822943970058036665661144537831658646492088707747292249493384317484'); -console.assert(BigDecimal.exp(BigDecimal.BigDecimal(0), {maximumFractionDigits: 0, roundingMode: 'half-even'}).toString() === '1'); // fromString //console.assert(BigDecimal.BigDecimal(' +1.2e+3 ').toString() === '120'); @@ -249,6 +249,9 @@ console.assert(BigDecimal.BigDecimal('999999999999999999999.4').toFixed(0) === ' //console.assert(BigDecimal.BigDecimal('1e+21').toFixed(0) === '1e+21'); console.assert(BigDecimal.BigDecimal('-1e-100').toFixed(10) === '-0.0000000000'); +const testMath = true; +if (testMath) { + // BigDecimal.log console.assert(BigDecimal.log(BigDecimal.BigDecimal(10), { maximumSignificantDigits: 16, roundingMode: 'half-even' }).toString() === '2.302585092994046'); console.assert(BigDecimal.log(BigDecimal.BigDecimal(2), { maximumSignificantDigits: 16, roundingMode: 'half-even' }).toString() === '0.6931471805599453'); @@ -266,6 +269,9 @@ console.assert(BigDecimal.log(BigDecimal.BigDecimal('2.718281830905498'), { maxi console.assert(BigDecimal.log(BigDecimal.BigDecimal('1e-10'), { maximumSignificantDigits: 8, roundingMode: 'half-even' }).toString() === '-23.025851'); // BigDecimal.exp +//console.assert(BigDecimal.exp(BigDecimal.BigDecimal('1e+100'), { maximumSignificantDigits: 1, roundingMode: 'half-even' }).toString() === '2e+4342944819032518276511289189166050822943970058036665661144537831658646492088707747292249493384317483'); +//console.assert(BigDecimal.exp(BigDecimal.BigDecimal('-1e+100'), { maximumSignificantDigits: 1, roundingMode: 'half-even' }).toString() === '7e-4342944819032518276511289189166050822943970058036665661144537831658646492088707747292249493384317484'); +console.assert(BigDecimal.exp(BigDecimal.BigDecimal(0), {maximumFractionDigits: 0, roundingMode: 'half-even'}).toString() === '1'); console.assert(BigDecimal.exp(BigDecimal.BigDecimal(1), { maximumSignificantDigits: 16, roundingMode: 'half-even' }).toString() === '2.718281828459045'); console.assert(BigDecimal.exp(BigDecimal.BigDecimal(700), { maximumSignificantDigits: 16, roundingMode: 'half-even' }).toString() === '1.014232054735005e+304'); console.assert(BigDecimal.exp(BigDecimal.BigDecimal(-10), { maximumSignificantDigits: 16, roundingMode: 'half-even' }).toString() === '0.00004539992976248485'); @@ -315,6 +321,8 @@ console.assert(BigDecimal.sqrt(BigDecimal.BigDecimal(100), {maximumFractionDigit console.assert(BigDecimal.sqrt(BigDecimal.BigDecimal('0.0022543340705052373e+1'), {maximumSignificantDigits: 133, roundingMode: 'floor'}).toString() === '0.1501443995127769426052976079792471072949865532195559797216663259395716567795895845959219116376275197595509976588342401869302170077707'); console.assert(BigDecimal.sqrt(BigDecimal.BigDecimal('0.8064902266570342e+6'), {maximumSignificantDigits: 137, roundingMode: 'ceil'}).toString() === '898.04800910476618015029976392760697926908695002996368102408741467418735302842706678658172375120578579550953111677275701668340441136770143'); +} + //BigDecimal2 // random tests: @@ -323,7 +331,7 @@ console.time('testing against decimal.js'); for (var c = 0; c < 10000; c += 1) { var aValue = ((-1 + 2 * Math.random()) + 'e+' + (Math.floor(Math.random() * 20) - 10)).replace(/\+\-/g, '-'); var bValue = ((-1 + 2 * Math.random()) + 'e+' + (Math.floor(Math.random() * 20) - 10)).replace(/\+\-/g, '-'); - var operations = 'add subtract multiply divide log exp sin cos atan sqrt'.split(' '); + var operations = ('add subtract multiply divide' + (testMath ? ' log exp sin cos atan sqrt' : '')).split(' '); var operation = operations[Math.floor(Math.random() * operations.length)]; //var roundingType = Math.random() < 0.5 ? 'maximumSignificantDigits' : 'maximumFractionDigits'; var roundingType = 'maximumSignificantDigits'; @@ -467,10 +475,12 @@ const someBenchmarks = function (BigDecimal, BASE) { }; +if (testMath) { console.log('%cUsing BigDecimal:', 'font-weight: bold'); someBenchmarks(BigDecimal, 10); console.log('%cUsing BigFloat:', 'font-weight: bold'); someBenchmarks(BigFloat, 2); +} globalThis.BigFloat = BigFloat; @@ -479,21 +489,27 @@ console.assert(BigFloat.divide(BigFloat.BigFloat(13835058055282163711n), BigFloa console.assert(BigFloat.BigFloat(1).toPrecision(101) === '1.' + '0'.repeat(100)); console.assert(BigFloat.BigFloat(46892389.03583745).toPrecision(34) === '46892389.03583744913339614868164063'); console.assert(BigFloat.BigFloat(-9422.84286622639).toExponential(36) === '-9.422842866226390469819307327270507813e+3'); +if (testMath) { console.assert(BigFloat.exp(BigFloat.BigFloat(710), { maximumSignificantDigits: 1, roundingMode: 'half-even' }).toPrecision(1) === '2e+308'); console.assert(BigFloat.exp(BigFloat.BigFloat(-739), { maximumSignificantDigits: 9, roundingMode: 'half-even' }).toPrecision(4) === '1.139e-321'); +} console.assert(BigFloat.BigFloat(9.478349671985029e+100).toExponential(0) === '9e+100'); // bug console.assert(BigFloat.BigFloat(9.5e+307).toExponential(0) === '9e+307'); console.assert(BigFloat.BigFloat(-9.460115477371994e+122).toExponential(0) === '-9e+122'); // bug +if (testMath) { var a = BigFloat.exp(BigFloat.exp(BigFloat.BigFloat(711), {roundingMode: 'floor', maximumSignificantDigits: 1}), {roundingMode: 'floor', maximumSignificantDigits: 1}); console.assert(BigFloat.cmp(a, BigFloat.BigFloat(1)) > 0); // bug console.assert(BigFloat.cmp(BigFloat.BigFloat(1), a) < 0); // bug console.assert(BigFloat.cmp(BigFloat.unaryMinus(a), BigFloat.BigFloat(-1)) < 0); // bug console.assert(BigFloat.cmp(BigFloat.BigFloat(-1), BigFloat.unaryMinus(a)) > 0); // bug +} console.assert(BigFloat.BigFloat(-1317.6236094638452).toExponential(42) === '-1.317623609463845241407398134469985961914063e+3'); // bug +if (testMath) { var x = BigFloat.log(BigFloat.BigFloat(8), {maximumSignificantDigits: 138, roundingMode: 'floor'}); x = BigFloat.divide(x, BigFloat.BigFloat(4)); console.assert(BigFloat.exp(BigFloat.BigFloat(x), { maximumSignificantDigits: 138, roundingMode: 'floor' }).toFixed(2) === '1.68'); // bug (infinite loop) +} console.assert(BigFloat.toNumber(BigFloat.divide(BigFloat.BigFloat(3), BigFloat.BigFloat(2), { maximumSignificantDigits: 1, roundingMode: 'up' })) === 2); console.assert(BigFloat.toNumber(BigFloat.divide(BigFloat.BigFloat(3), BigFloat.BigFloat(-2), { maximumSignificantDigits: 1, roundingMode: 'up' })) === -2); @@ -528,6 +544,7 @@ var roundNumber = function (number, precision) { return v - (v - number);//? }; +if (testMath) { console.time('Math for small values'); for (var c = 0; c < 10000; c += 1) { var number = roundNumber(randomNumber(), 18); @@ -553,6 +570,7 @@ for (var c = 0; c < 10000; c += 1) { } } console.timeEnd('Math for small values'); +} console.time(); var s = 0;