mirror of
https://github.com/MikeMcl/decimal.js.git
synced 2024-10-27 20:34:12 +00:00
v3.0.0
This commit is contained in:
parent
7524fbaefe
commit
e02587a173
13
README.md
13
README.md
@ -9,7 +9,7 @@ An arbitrary-precision Decimal type for JavaScript.
|
||||
- Simple API but full-featured
|
||||
- Replicates the `toExponential`, `toFixed`, `toPrecision` and `toString` methods of JavaScript's Number type
|
||||
- Includes a `toFraction` and correctly-rounded `exp`, `ln`, `log` and `sqrt` functions
|
||||
- Supports non-integer powers (although performance is limited)
|
||||
- Supports non-integer powers
|
||||
- Works with numbers with or without fraction digits in bases from 2 to 64 inclusive
|
||||
- Stores values in an accessible decimal floating-point format
|
||||
- No dependencies
|
||||
@ -136,11 +136,11 @@ Many of the methods of JavaScript's Math object are also replicated
|
||||
Decimal.sqrt('6.98372465832e+9823') // '8.3568682281821340204e+4911'
|
||||
Decimal.pow(2, 0.0979843) // '1.0702770511687781839'
|
||||
|
||||
The value of a Decimal is stored in a decimal floating point format in terms of a coefficient, exponent and sign.
|
||||
The value of a Decimal is stored in a floating point format in terms of a coefficient, exponent and sign.
|
||||
|
||||
x = new Decimal(-123.456);
|
||||
x.c // '1,2,3,4,5,6' coefficient (i.e. significand)
|
||||
x.e // 2 exponent
|
||||
x = new Decimal(-12345.67);
|
||||
x.c // [ 12345, 6700000 ] coefficient (base 10000)
|
||||
x.e // 4 exponent (base 10)
|
||||
x.s // -1 sign
|
||||
|
||||
For further information see the [API](http://mikemcl.github.io/decimal.js/) reference in the *doc* directory.
|
||||
@ -198,6 +198,9 @@ See LICENCE.
|
||||
|
||||
## Change Log
|
||||
|
||||
####3.0.0
|
||||
* 4/06/2014 `random` simplified. Major internal changes mean the properties of a Decimal must now be considered read-only.
|
||||
|
||||
####2.1.0
|
||||
* 4/06/2014 Amend UMD
|
||||
|
||||
|
1920
decimal.js
1920
decimal.js
File diff suppressed because it is too large
Load Diff
4
decimal.min.js
vendored
4
decimal.min.js
vendored
File diff suppressed because one or more lines are too long
117
doc/API.html
117
doc/API.html
@ -492,31 +492,17 @@ x.equals(y) // true</pre>
|
||||
|
||||
|
||||
<h5 id="Drand">
|
||||
random<code class='inset'>.random([limit [, sd]]) <i>⇒ Decimal</i></code>
|
||||
random<code class='inset'>.random([dp]) <i>⇒ Decimal</i></code>
|
||||
</h5>
|
||||
<p><code>dp</code>: <i>number</i>: integer, 0 to 1e+9 inclusive</p>
|
||||
<p>
|
||||
<code>limit</code>: <i>number|string|Decimal</i><br /> Default value: <code>1</code><br />
|
||||
<code>sd</code>: <i>number</i>: integer, 1 to 1e+9 inclusive<br />
|
||||
<i>See <code><a href="#decimal">Decimal</a></code> for further parameter details.</i>
|
||||
Returns a new Decimal with a pseudo-random value equal to or greater than <code>0</code> and
|
||||
less than <code>1</code>.
|
||||
</p>
|
||||
<p>
|
||||
Returns a new Decimal with a pseudo-random value equal to or greater in magnitude than
|
||||
<code>0</code> and lower in magnitude than <code>limit</code>, and with the same sign as
|
||||
<code>limit</code>.
|
||||
</p>
|
||||
<p>
|
||||
If <code>limit</code> is omitted then it will be <code>1</code> and the return value will
|
||||
have <a href='#precision'><code>precision</code></a> significant digits (or less if there are
|
||||
trailing zeros produced).
|
||||
</p>
|
||||
<p>
|
||||
If <code>limit</code> is included and <code>sd</code> is omitted then the return value
|
||||
will be an integer. If <code>sd</code> is included, the return value will have
|
||||
<code>sd</code> significant digits (or less if there are trailing zeros produced).
|
||||
</p>
|
||||
<p>
|
||||
If <code>limit</code> is a high value be sure to include a precision, otherwise this method
|
||||
may be slow to return because all integer digits will be generated.
|
||||
The return value will have <code>dp</code></a> decimal places (or less if trailing zeros are
|
||||
produced). If <code>dp</code> is omitted then the number of decimal places will
|
||||
default to the current <a href='#precision'><code>precision</code></a> setting.
|
||||
</p>
|
||||
<p>
|
||||
Depending on the value of a Decimal constructor's <a href='#crypto'><code>crypto</code></a>
|
||||
@ -530,33 +516,11 @@ x.equals(y) // true</pre>
|
||||
<code>crypto</code> methods is to be used, the value of a returned Decimal should be
|
||||
cryptographically-secure and statistically indistinguishable from a random value.
|
||||
</p>
|
||||
<pre>// A value in the range [0, 1) with precision significant digits
|
||||
Decimal.config({ precision: 10 })
|
||||
<pre>Decimal.config({ precision: 10 })
|
||||
Decimal.random() // '0.4117936847'
|
||||
|
||||
// A value in the range [0, 1) with 20 significant digits
|
||||
Decimal.random(1, 20) // '0.48193327636914089007'
|
||||
Decimal.random(20) // '0.78193327636914089009'</pre>
|
||||
|
||||
// An integer in the range [0, 1)
|
||||
Decimal.random(1) // '0' (always zero)
|
||||
|
||||
// An integer in the range [0, 10)
|
||||
Decimal.random(10) // '6'
|
||||
|
||||
// An integer in the range (-100, 0]
|
||||
Decimal.random(-100) // '-82'
|
||||
|
||||
// An integer in the range [0, 9e9999999999)
|
||||
Decimal.random('9e99999999999') // A browser will hang
|
||||
|
||||
// A value in the range [0, 9e9999999999) with 10 significant digits
|
||||
Decimal.random('9e99999999999', 25) // '1.508652055e+99999999999'
|
||||
|
||||
// A value in the range (-0.0125, 0] with 16 significant digits
|
||||
Decimal.random(-0.0125, 16) // '-0.0001963482803540358'
|
||||
|
||||
// A value in the range [0, 0.9) with 1 significant digit
|
||||
Decimal.random(0.9, 1) // '0.2'</pre>
|
||||
|
||||
|
||||
|
||||
@ -869,7 +833,12 @@ Decimal.modulo // 9</pre>
|
||||
</p>
|
||||
<p>
|
||||
If neither function is supported by the host environment or if <code>crypto</code> is falsey
|
||||
then the source of randomness will be <code>Math.random</code>.
|
||||
then the source of randomness will be <code>Math.random</code>. If the <code>crypto</code>
|
||||
property is set directly (i.e. without using <code>config</code>) to <code>true</code>, then
|
||||
at the time the <code>random</code> method is called, if
|
||||
<a href='#errors'><code>errors</code></a> is <code>true</code>, an error will be thrown if the
|
||||
<code>crypto</code> methods are unavailable.
|
||||
</p>
|
||||
</p>
|
||||
<pre>
|
||||
Decimal.crypto // false
|
||||
@ -1746,9 +1715,9 @@ JSON.parse(str, function (key, val) {
|
||||
would be serialized, rather then the string returned by <code>valueOf</code>:</p>
|
||||
<pre>JSON.stringify( [x, y, z] )
|
||||
/*
|
||||
"[{"s":1,"e":459,"c":[1,7,7,7]},
|
||||
{"s":1,"e":2,"c":[2,3,5,4,3,2,5]},
|
||||
{"s":1,"e":-3,"c":[9,8,0,7,4]}]"
|
||||
"[{"s":1,"e":459,"c":[17770]},
|
||||
{"s":1,"e":2,"c":[235,4325000]},
|
||||
{"s":1,"e":-3,"c":[98074]}]"
|
||||
*/</pre>
|
||||
|
||||
|
||||
@ -1823,8 +1792,7 @@ z = new Decimal(-0)
|
||||
</p>
|
||||
<p>
|
||||
The performance of this method degrades exponentially with increasing digits. For
|
||||
non-integer exponents in particular, even when only quite a small number of significant
|
||||
digits is required, the performance of this method may not be adequate.
|
||||
non-integer exponents in particular, the performance of this method may not be adequate.
|
||||
</p>
|
||||
<pre>
|
||||
Math.pow(0.7, 2) // 0.48999999999999994
|
||||
@ -2038,7 +2006,7 @@ x.valueOf() // '1.777e+457'</pre>
|
||||
<td class='centre' id='coefficient'><b>c</b></td>
|
||||
<td>coefficient<sup>*</sup></td>
|
||||
<td><i>number</i><code style='color:#000'>[]</code></td>
|
||||
<td> Array of single digits</td>
|
||||
<td> Array of integers, each 0 - 1e7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='centre' id='exponent'><b>e</b></td>
|
||||
@ -2058,19 +2026,23 @@ x.valueOf() // '1.777e+457'</pre>
|
||||
The value of any of the three properties may also be <code>null</code>.
|
||||
</p>
|
||||
<p>
|
||||
The value of a Decimal is stored in a normalised decimal floating point
|
||||
format which corresponds to the value's <code><a href='#toE'>toExponential</a></code> form,
|
||||
with the decimal point to be positioned after the most significant
|
||||
(left-most) digit of the coefficient.
|
||||
The properties are best considered to be read-only.
|
||||
</p>
|
||||
<p>
|
||||
Note that, as with JavaScript numbers, the original exponent and
|
||||
fractional trailing zeros are not preserved.
|
||||
From version 3 of this library, the value of a Decimal is stored in a normalised base
|
||||
<code>10000</code> floating point format. While previously it was acceptable to change the
|
||||
exponent of a Decimal by writing to its exponent property directly, this is no longer
|
||||
recommended (as the number of digits in the first element of the coefficient array is
|
||||
dependent on the exponent, so the coefficient would also need to be altered).
|
||||
</p>
|
||||
<p>
|
||||
As with JavaScript numbers, the original exponent and fractional trailing zeros of a number
|
||||
are not preserved.
|
||||
</p>
|
||||
<pre>
|
||||
x = new Decimal(0.123) // '0.123'
|
||||
x.toExponential() // '1.23e-1'
|
||||
x.c // '1,2,3'
|
||||
x.c // [ 1230000 ]
|
||||
x.e // -1
|
||||
x.s // 1
|
||||
|
||||
@ -2078,31 +2050,11 @@ y = new Number(-123.4567000e+2) // '-12345.67'
|
||||
y.toExponential() // '-1.234567e+4'
|
||||
z = new Decimal('-123.4567000e+2') // '-12345.67'
|
||||
z.toExponential() // '-1.234567e+4'
|
||||
z.c // '1,2,3,4,5,6,7'
|
||||
z.c // [ 12345, 6700000 ]
|
||||
z.e // 4
|
||||
z.s // -1</pre>
|
||||
|
||||
|
||||
<p>
|
||||
A Decimal is mutable in the sense that the value of its properties can
|
||||
be changed.<br />
|
||||
For example, to rapidly shift a value by a power of 10:
|
||||
</p>
|
||||
<pre>
|
||||
x = new Decimal('1234.000') // '1234'
|
||||
x.toExponential() // '1.234e+3'
|
||||
x.c // '1,2,3,4'
|
||||
x.e // 3
|
||||
|
||||
x.e = -5
|
||||
x // '0.00001234'</pre>
|
||||
<p>
|
||||
If changing the coefficient array directly, which is not recommended, be
|
||||
careful to avoid leading or trailing zeros (unless zero itself is being
|
||||
represented).
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h4 id="zero-nan-infinity">Zero, NaN and Infinity</h4>
|
||||
<p>
|
||||
@ -2276,6 +2228,11 @@ y.s // -1</pre>
|
||||
<td>argument not a boolean or binary digit</td>
|
||||
<td>Ignore</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>random</code></td>
|
||||
<td><code>crypto</code> unavailable</td>
|
||||
<td>Use <code>Math.random</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan=4>
|
||||
<code>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "decimal.js",
|
||||
"description": "An arbitrary-precision Decimal type for JavaScript.",
|
||||
"version": "2.1.0",
|
||||
"version": "3.0.0",
|
||||
"keywords": [
|
||||
"arbitrary",
|
||||
"precision",
|
||||
@ -31,6 +31,6 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "node ./test/every-test.js",
|
||||
"build": "uglifyjs decimal.js -c -m -o decimal.min.js --preamble '/* decimal.js v2.1.0 https://github.com/MikeMcl/decimal.js/LICENCE */'"
|
||||
"build": "uglifyjs decimal.js -c -m -o decimal.min.js --preamble '/* decimal.js v3.0.0 https://github.com/MikeMcl/decimal.js/LICENCE */'"
|
||||
}
|
||||
}
|
@ -45,7 +45,6 @@
|
||||
<!-- <script src='../toSD.js'></script> -->
|
||||
<!-- <script src='../toStringEtc.js'></script> -->
|
||||
<!-- <script src='../trunc.js'></script> -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
122
test/random.js
122
test/random.js
@ -1,6 +1,6 @@
|
||||
var count = (function random(Decimal) {
|
||||
var start = +new Date(),
|
||||
error, i, j, limit, log, pr, u,
|
||||
dp, error, i, j, k, log, m, r,
|
||||
passed = 0,
|
||||
total = 0;
|
||||
|
||||
@ -14,20 +14,7 @@ var count = (function random(Decimal) {
|
||||
}
|
||||
|
||||
if (!Decimal && typeof require === 'function') {
|
||||
Decimal = require('../decimal');
|
||||
}
|
||||
|
||||
function assert(result, r, message) {
|
||||
total++;
|
||||
if (result === true) {
|
||||
passed++;
|
||||
//log('\n r: ' + r);
|
||||
} else {
|
||||
error('\n Test number: ' + total + ' failed');
|
||||
error(' r: ' + r);
|
||||
error(' ' + message);
|
||||
//process.exit();
|
||||
}
|
||||
Decimal = require('../decimal.js');
|
||||
}
|
||||
|
||||
function assertException(func, message) {
|
||||
@ -49,74 +36,65 @@ var count = (function random(Decimal) {
|
||||
}
|
||||
}
|
||||
|
||||
function T(limit, pr){
|
||||
var i, r, d;
|
||||
|
||||
if ( !limit ) {
|
||||
limit = new Decimal(1);
|
||||
pr = Decimal.precision;
|
||||
}
|
||||
|
||||
for ( i = 0; i < 17; i++ ) {
|
||||
r = Decimal.random(limit, pr);
|
||||
//log(r.toString());
|
||||
d = r.c.length;
|
||||
|
||||
if ( pr == null ) {
|
||||
d = Math.max(d, r.e + 1) - r.e - 1;
|
||||
assert(d === 0, r, 'dp is not 0: ' + d);
|
||||
} else {
|
||||
assert(d <= pr, r, 'sd: ' + d + ' > pr: ' + pr);
|
||||
}
|
||||
|
||||
assert(r.gte(0), r, 'r < 0');
|
||||
assert(r.lt(limit), r, 'r >= limit: ' + limit);
|
||||
}
|
||||
}
|
||||
|
||||
log('\n Testing random...');
|
||||
|
||||
// First iteration crypto: false, second iteration crypto: true.
|
||||
Decimal.config({ crypto: false, errors: true });
|
||||
Decimal.config({ errors: true, crypto: false });
|
||||
|
||||
for ( i = 0; i < 2; i++ ) {
|
||||
//log( '\n crypto: ' + Decimal.crypto );
|
||||
for ( i = 0; i < 9996; i++ ) {
|
||||
|
||||
Decimal.precision = Math.random() * 100 + 1 | 0;
|
||||
//log( Decimal.precision );
|
||||
//Decimal.crypto = false;
|
||||
//Decimal.crypto = true;
|
||||
// 50% chance that Decimal.crypto is true.
|
||||
//Decimal.crypto = Math.random() > 0.5;
|
||||
|
||||
for ( j = 0; j < 10; j++ ) {
|
||||
|
||||
T();
|
||||
T(u);
|
||||
T(null);
|
||||
T(1);
|
||||
T(1, u);
|
||||
T(1, null);
|
||||
T(10);
|
||||
T(1000);
|
||||
|
||||
// limit will have 1 - 17 integer digits and 1 - 17 fraction digits.
|
||||
limit = +(Math.random() + '').slice(2, Math.random() * 17 + 3 | 0) +
|
||||
(Math.random() + '').slice(1, Math.random() * 17 + 3 | 0);
|
||||
|
||||
if ( +limit == 0 ) {
|
||||
limit = 1;
|
||||
if ( Math.random() > 0.5 ) {
|
||||
dp = Decimal.precision = Math.random() * 10 + 1 | 0;
|
||||
r = Decimal.random();
|
||||
} else {
|
||||
dp = Math.random() * 10 | 0;
|
||||
r = Decimal.random(dp);
|
||||
}
|
||||
|
||||
//log(' limit: ' + limit);
|
||||
//log(r.toString());
|
||||
|
||||
T(limit);
|
||||
if ( r.c[0] ) {
|
||||
j = r.c.length;
|
||||
k = r.c[j - 1];
|
||||
j *= 7;
|
||||
|
||||
// Precision. Integer 1 - 80.
|
||||
pr = Math.random() * 80 + 1 | 0;
|
||||
|
||||
//log(' pr: ' + pr);
|
||||
|
||||
T(limit, pr);
|
||||
// Decrement for trailing zeros in last element of r.c.
|
||||
for ( ; k % 10 === 0; k /= 10, j-- );
|
||||
} else {
|
||||
j = 0;
|
||||
}
|
||||
|
||||
Decimal.config({ crypto: true });
|
||||
// Check number of decimal places (j is actual dp).
|
||||
if ( j > dp ) {
|
||||
m = ' r.c.length - r.e - 1 > dp';
|
||||
|
||||
// Check 0 <= r < 1
|
||||
} else if ( r.lt(0) || r.gte(1) ) {
|
||||
m = ' r.lt(0) || r.gte(1)';
|
||||
|
||||
// Check that the attributes of r are formed correctly.
|
||||
} else if ( !r.eq( new Decimal(r) ) || !r.eq( new Decimal( r.toString() ) ) ) {
|
||||
m = ' !r.eq( new Decimal(r) ) || !r.eq( new Decimal( r.toString() ) )';
|
||||
}
|
||||
|
||||
total++;
|
||||
|
||||
if (m) {
|
||||
error('\n Test number: ' + total + ' failed');
|
||||
error(m);
|
||||
error(' r: ' + r);
|
||||
error(' r.c: ' + r.c);
|
||||
error(' r.e: ' + r.e);
|
||||
error(' r.s: ' + r.s);
|
||||
error(' dp: ' + dp);
|
||||
m = null;
|
||||
} else {
|
||||
passed++;
|
||||
}
|
||||
}
|
||||
|
||||
assertException(function () { Decimal.random(Infinity) }, 'Infinity');
|
||||
|
@ -15,7 +15,7 @@ var count = (function toFixed(Decimal) {
|
||||
str.replace('\n', '<br>') + '</div>' };
|
||||
}
|
||||
|
||||
if (!Decimal && typeof require === 'function') Decimal = require('../decimal');
|
||||
if (!Decimal && typeof require === 'function') Decimal = require('../decimal.js');
|
||||
|
||||
function assert(expected, actual) {
|
||||
total++;
|
||||
@ -1051,11 +1051,8 @@ var count = (function toFixed(Decimal) {
|
||||
T('123.45000000000', '12.345e1', '1.1e1');
|
||||
|
||||
T('123.5', '12.345e1', 1);
|
||||
T('120', '12.345e1', '-1');
|
||||
T('0', '12.345e1', -23);
|
||||
T('123.45', '12.345e1', '-1');
|
||||
T('123.45', '12.345e1', 1e9 + 1);
|
||||
T('123', '12.345e1', '-0.01');
|
||||
T('123', '12.345e1', '-1e-1');
|
||||
T('123.45', '12.345e1', Infinity);
|
||||
T('123.45', '12.345e1', '-Infinity');
|
||||
|
||||
@ -1070,7 +1067,7 @@ var count = (function toFixed(Decimal) {
|
||||
T('1', 0.55, 0);
|
||||
T('1', 0.56, 0);
|
||||
T('-1', -0.54, 0);
|
||||
T('-0', -0.5, 0); // test no. 1307
|
||||
T('-0', -0.5, 0);
|
||||
T('-1', -0.56, 0);
|
||||
T('-0.5', -0.5, 1);
|
||||
T('1.3', 1.25, 1);
|
||||
@ -1119,27 +1116,6 @@ var count = (function toFixed(Decimal) {
|
||||
T('-1.00000000000000000', '-1.000000000000000000005', '17')
|
||||
T('-1.00000000000000000001', '-1.000000000000000000005', '20')
|
||||
|
||||
Decimal.rounding = 4;
|
||||
|
||||
T('1000', 999.5, -1);
|
||||
T('1000', 999.5, -2);
|
||||
T('1000', 999.5, -3);
|
||||
T('0', 999.5, -4);
|
||||
T('0', 999.5, -5);
|
||||
|
||||
T('0', 0.000123456, -1);
|
||||
T('9870', 9870.000123456, -1);
|
||||
T('9900', 9870.000123456, -2);
|
||||
T('10000', 9870.000123456, -3);
|
||||
|
||||
Decimal.rounding = 1;
|
||||
|
||||
T('990', 999.5, -1);
|
||||
T('900', 999.5, -2);
|
||||
T('0', 999.5, -3);
|
||||
T('0', 999.5, -4);
|
||||
T('0', 999.5, -5);
|
||||
|
||||
log('\n ' + passed + ' of ' + total + ' tests passed in ' + (+new Date() - start) + ' ms \n');
|
||||
return [passed, total];
|
||||
})(this.Decimal);
|
||||
|
Loading…
Reference in New Issue
Block a user