Skip to content

Commit

Permalink
transpiling precision tests wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kroitor committed May 30, 2018
1 parent 23c5c12 commit 0480db2
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 134 deletions.
8 changes: 4 additions & 4 deletions js/test/base/functions/test.number.js
Expand Up @@ -70,10 +70,10 @@ assert (decimalToPrecision ('12.3456', ROUND, 0, DECIMAL_PLACES) === '12');
// assert (decimalToPrecision ('123.456', ROUND, -1, DECIMAL_PLACES) === '120'); // not yet supported
// assert (decimalToPrecision ('123.456', ROUND, -2, DECIMAL_PLACES) === '100'); // not yet supported

assert (decimalToPrecision ( '9.999', ROUND, 3, DECIMAL_PLACES) === '9.999');
assert (decimalToPrecision ( '9.999', ROUND, 2, DECIMAL_PLACES) === '10');
assert (decimalToPrecision ( '9.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '10.00');
assert (decimalToPrecision ( '99.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '100.00');
assert (decimalToPrecision ('9.999', ROUND, 3, DECIMAL_PLACES) === '9.999');
assert (decimalToPrecision ('9.999', ROUND, 2, DECIMAL_PLACES) === '10');
assert (decimalToPrecision ('9.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '10.00');
assert (decimalToPrecision ('99.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '100.00');
assert (decimalToPrecision ('-99.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '-100.00');

// ----------------------------------------------------------------------------
Expand Down
187 changes: 120 additions & 67 deletions php/test/decimal_to_precision.php
@@ -1,7 +1,6 @@
<?php

include_once ('ccxt.php');

use ccxt\Exchange;
use const ccxt\DECIMAL_PLACES;
use const ccxt\NO_PADDING;
Expand All @@ -10,7 +9,7 @@
use const ccxt\SIGNIFICANT_DIGITS;
use const ccxt\TRUNCATE;

//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// testDecimalToPrecisionErrorHandling
//
// $this->expectException ('ccxt\\BaseError');
Expand All @@ -21,91 +20,145 @@
// $this->expectExceptionMessageRegExp ('/Invalid number/');
// Exchange::decimalToPrecision ('foo');

//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

// PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
// https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code


// ----------------------------------------------------------------------------
// number_to_string works, not supported in Python and PHP yet

// assert (number_to_string (-7.9e-7) === '-0.0000007899999999999999');
// assert (number_to_string ( 7.9e-7) === '0.0000007899999999999999');

// assert (number_to_string (-12.345) === '-12.345');
// assert (number_to_string ( 12.345) === '12.345');

// assert (number_to_string (0) === '0');

// ----------------------------------------------------------------------------
// testDecimalToPrecisionTruncationToNDigitsAfterDot

assert (Exchange::decimal_to_precision ('12.3456000', TRUNCATE, 100, DECIMAL_PLACES) === '12.3456');
assert (Exchange::decimal_to_precision ('12.3456', TRUNCATE, 100, DECIMAL_PLACES) === '12.3456');
assert (Exchange::decimal_to_precision ('12.3456', TRUNCATE, 4, DECIMAL_PLACES) === '12.3456');
assert (Exchange::decimal_to_precision ('12.3456', TRUNCATE, 3, DECIMAL_PLACES) === '12.345');
assert (Exchange::decimal_to_precision ('12.3456', TRUNCATE, 2, DECIMAL_PLACES) === '12.34');
assert (Exchange::decimal_to_precision ('12.3456', TRUNCATE, 1, DECIMAL_PLACES) === '12.3');
assert (Exchange::decimal_to_precision ('12.3456', TRUNCATE, 0, DECIMAL_PLACES) === '12');
assert (decimal_to_precision ('12.3456000', TRUNCATE, 100, DECIMAL_PLACES) === '12.3456');
assert (decimal_to_precision ('12.3456', TRUNCATE, 100, DECIMAL_PLACES) === '12.3456');
assert (decimal_to_precision ('12.3456', TRUNCATE, 4, DECIMAL_PLACES) === '12.3456');
assert (decimal_to_precision ('12.3456', TRUNCATE, 3, DECIMAL_PLACES) === '12.345');
assert (decimal_to_precision ('12.3456', TRUNCATE, 2, DECIMAL_PLACES) === '12.34');
assert (decimal_to_precision ('12.3456', TRUNCATE, 1, DECIMAL_PLACES) === '12.3');
assert (decimal_to_precision ('12.3456', TRUNCATE, 0, DECIMAL_PLACES) === '12');

// assert (Exchange::decimal_to_precision ('12.3456', TRUNCATE, -1, DECIMAL_PLACES) === '10'); // not supported yet
// assert (Exchange::decimal_to_precision ('123.456', TRUNCATE, -2, DECIMAL_PLACES) === '120'); // not supported yet
// assert (Exchange::decimal_to_precision ('123.456', TRUNCATE, -3, DECIMAL_PLACES) === '100'); // not supported yet
// assert (decimal_to_precision ('12.3456', TRUNCATE, -1, DECIMAL_PLACES) === '10'); // not yet supported
// assert (decimal_to_precision ('123.456', TRUNCATE, -2, DECIMAL_PLACES) === '120'); // not yet supported
// assert (decimal_to_precision ('123.456', TRUNCATE, -3, DECIMAL_PLACES) === '100'); // not yet supported

//-----------------------------------------------------------------------------
assert (decimal_to_precision ('0', TRUNCATE, 0, DECIMAL_PLACES) === '0');

// ----------------------------------------------------------------------------
// testDecimalToPrecisionTruncationToNSignificantDigits

assert (Exchange::decimal_to_precision ('0.000123456700', TRUNCATE, 100, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001234567');
assert (Exchange::decimal_to_precision ('0.0001234567', TRUNCATE, 100, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001234567');
assert (Exchange::decimal_to_precision ('0.0001234567', TRUNCATE, 7, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001234567');
assert (decimal_to_precision ('0.000123456700', TRUNCATE, 100, SIGNIFICANT_DIGITS) === '0.0001234567');
assert (decimal_to_precision ('0.0001234567', TRUNCATE, 100, SIGNIFICANT_DIGITS) === '0.0001234567');
assert (decimal_to_precision ('0.0001234567', TRUNCATE, 7, SIGNIFICANT_DIGITS) === '0.0001234567');

assert (decimal_to_precision ('0.000123456', TRUNCATE, 6, SIGNIFICANT_DIGITS) === '0.000123456');
assert (decimal_to_precision ('0.000123456', TRUNCATE, 5, SIGNIFICANT_DIGITS) === '0.00012345');
assert (decimal_to_precision ('0.000123456', TRUNCATE, 2, SIGNIFICANT_DIGITS) === '0.00012');
assert (decimal_to_precision ('0.000123456', TRUNCATE, 1, SIGNIFICANT_DIGITS) === '0.0001');

assert (Exchange::decimal_to_precision ('0.000123456', TRUNCATE, 6, SIGNIFICANT_DIGITS, NO_PADDING) === '0.000123456');
assert (Exchange::decimal_to_precision ('0.00012345', TRUNCATE, 5, SIGNIFICANT_DIGITS, NO_PADDING) === '0.00012345');
assert (Exchange::decimal_to_precision ('0.00012', TRUNCATE, 2, SIGNIFICANT_DIGITS, NO_PADDING) === '0.00012');
assert (Exchange::decimal_to_precision ('0.0001', TRUNCATE, 1, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 10, SIGNIFICANT_DIGITS) === '123.0000987');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 8, SIGNIFICANT_DIGITS) === '123.00009');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 7, SIGNIFICANT_DIGITS) === '123');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 7, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '123.0000');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 4, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '123.0');

assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 10, SIGNIFICANT_DIGITS, NO_PADDING) === '123.0000987');
assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 8, SIGNIFICANT_DIGITS, NO_PADDING) === '123.00009');
assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 7, SIGNIFICANT_DIGITS, NO_PADDING) === '123');
assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 7, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '123.0000');
assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 4, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '123.0');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 2, SIGNIFICANT_DIGITS) === '120');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 1, SIGNIFICANT_DIGITS) === '100');
assert (decimal_to_precision ('123.0000987654', TRUNCATE, 1, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '100');

assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 2, SIGNIFICANT_DIGITS, NO_PADDING) === '120');
assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 1, SIGNIFICANT_DIGITS, NO_PADDING) === '100');
assert (Exchange::decimal_to_precision ('123.0000987654', TRUNCATE, 1, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '100');
assert (decimal_to_precision ('0', TRUNCATE, 0, SIGNIFICANT_DIGITS) === '0');

//-----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// testDecimalToPrecisionRoundingToNDigitsAfterDot

assert (Exchange::decimal_to_precision ('12.3456000', ROUND, 100, DECIMAL_PLACES, NO_PADDING) === '12.3456');
assert (Exchange::decimal_to_precision ('12.3456', ROUND, 100, DECIMAL_PLACES, NO_PADDING) === '12.3456');
assert (Exchange::decimal_to_precision ('12.3456', ROUND, 4, DECIMAL_PLACES, NO_PADDING) === '12.3456');
assert (Exchange::decimal_to_precision ('12.3456', ROUND, 3, DECIMAL_PLACES, NO_PADDING) === '12.346');
assert (Exchange::decimal_to_precision ('12.3456', ROUND, 2, DECIMAL_PLACES, NO_PADDING) === '12.35');
assert (Exchange::decimal_to_precision ('12.3456', ROUND, 1, DECIMAL_PLACES, NO_PADDING) === '12.3');
assert (Exchange::decimal_to_precision ('12.3456', ROUND, 0, DECIMAL_PLACES, NO_PADDING) === '12');

// assert (Exchange::decimal_to_precision ('12.3456', ROUND, -1, DECIMAL_PLACES, NO_PADDING, '10'); // not supported yet
// assert (Exchange::decimal_to_precision ('123.456', ROUND, -1, DECIMAL_PLACES, NO_PADDING, '120'); // not supported yet
// assert (Exchange::decimal_to_precision ('123.456', ROUND, -2, DECIMAL_PLACES, NO_PADDING, '100'); // not supported yet

assert (Exchange::decimal_to_precision ('9.999', ROUND, 3, DECIMAL_PLACES, NO_PADDING) === '9.999');
assert (Exchange::decimal_to_precision ('9.999', ROUND, 2, DECIMAL_PLACES, NO_PADDING) === '10');
assert (Exchange::decimal_to_precision ('9.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '10.00');
assert (Exchange::decimal_to_precision ('99.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '100.00');
assert (Exchange::decimal_to_precision ('-99.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '-100.00');

//-----------------------------------------------------------------------------
assert (decimal_to_precision ('12.3456000', ROUND, 100, DECIMAL_PLACES) === '12.3456');
assert (decimal_to_precision ('12.3456', ROUND, 100, DECIMAL_PLACES) === '12.3456');
assert (decimal_to_precision ('12.3456', ROUND, 4, DECIMAL_PLACES) === '12.3456');
assert (decimal_to_precision ('12.3456', ROUND, 3, DECIMAL_PLACES) === '12.346');
assert (decimal_to_precision ('12.3456', ROUND, 2, DECIMAL_PLACES) === '12.35');
assert (decimal_to_precision ('12.3456', ROUND, 1, DECIMAL_PLACES) === '12.3');
assert (decimal_to_precision ('12.3456', ROUND, 0, DECIMAL_PLACES) === '12');

// assert (decimal_to_precision ('12.3456', ROUND, -1, DECIMAL_PLACES) === '10'); // not yet supported
// assert (decimal_to_precision ('123.456', ROUND, -1, DECIMAL_PLACES) === '120'); // not yet supported
// assert (decimal_to_precision ('123.456', ROUND, -2, DECIMAL_PLACES) === '100'); // not yet supported

assert (decimal_to_precision ('9.999', ROUND, 3, DECIMAL_PLACES) === '9.999');
assert (decimal_to_precision ('9.999', ROUND, 2, DECIMAL_PLACES) === '10');
assert (decimal_to_precision ('9.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '10.00');
assert (decimal_to_precision ('99.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '100.00');
assert (decimal_to_precision ('-99.999', ROUND, 2, DECIMAL_PLACES, PAD_WITH_ZERO) === '-100.00');

// ----------------------------------------------------------------------------
// testDecimalToPrecisionRoundingToNSignificantDigits

assert (Exchange::decimal_to_precision ('0.000123456700', ROUND, 100, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001234567');
assert (Exchange::decimal_to_precision ('0.0001234567', ROUND, 100, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001234567');
assert (Exchange::decimal_to_precision ('0.0001234567', ROUND, 7, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001234567');
assert (decimal_to_precision ('0.000123456700', ROUND, 100, SIGNIFICANT_DIGITS) === '0.0001234567');
assert (decimal_to_precision ('0.0001234567', ROUND, 100, SIGNIFICANT_DIGITS) === '0.0001234567');
assert (decimal_to_precision ('0.0001234567', ROUND, 7, SIGNIFICANT_DIGITS) === '0.0001234567');

assert (Exchange::decimal_to_precision ('0.000123456', ROUND, 6, SIGNIFICANT_DIGITS, NO_PADDING) === '0.000123456');
assert (Exchange::decimal_to_precision ('0.000123456', ROUND, 5, SIGNIFICANT_DIGITS, NO_PADDING) === '0.00012346');
assert (Exchange::decimal_to_precision ('0.000123456', ROUND, 4, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001235');
assert (Exchange::decimal_to_precision ('0.00012', ROUND, 2, SIGNIFICANT_DIGITS, NO_PADDING) === '0.00012');
assert (Exchange::decimal_to_precision ('0.0001', ROUND, 1, SIGNIFICANT_DIGITS, NO_PADDING) === '0.0001');
assert (decimal_to_precision ('0.000123456', ROUND, 6, SIGNIFICANT_DIGITS) === '0.000123456');
assert (decimal_to_precision ('0.000123456', ROUND, 5, SIGNIFICANT_DIGITS) === '0.00012346');
assert (decimal_to_precision ('0.000123456', ROUND, 4, SIGNIFICANT_DIGITS) === '0.0001235');
assert (decimal_to_precision ('0.00012', ROUND, 2, SIGNIFICANT_DIGITS) === '0.00012');
assert (decimal_to_precision ('0.0001', ROUND, 1, SIGNIFICANT_DIGITS) === '0.0001');

assert (Exchange::decimal_to_precision ('123.0000987654', ROUND, 7, SIGNIFICANT_DIGITS, NO_PADDING) === '123.0001');
assert (Exchange::decimal_to_precision ('123.0000987654', ROUND, 6, SIGNIFICANT_DIGITS, NO_PADDING) === '123');
assert (decimal_to_precision ('123.0000987654', ROUND, 7, SIGNIFICANT_DIGITS) === '123.0001');
assert (decimal_to_precision ('123.0000987654', ROUND, 6, SIGNIFICANT_DIGITS) === '123');

assert (Exchange::decimal_to_precision ('0.00098765', ROUND, 2, SIGNIFICANT_DIGITS, NO_PADDING) === '0.00099');
assert (Exchange::decimal_to_precision ('0.00098765', ROUND, 2, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '0.00099');
assert (decimal_to_precision ('0.00098765', ROUND, 2, SIGNIFICANT_DIGITS) === '0.00099');
assert (decimal_to_precision ('0.00098765', ROUND, 2, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '0.00099');

assert (Exchange::decimal_to_precision ('0.00098765', ROUND, 1, SIGNIFICANT_DIGITS, NO_PADDING) === '0.001');
assert (Exchange::decimal_to_precision ('0.00098765', ROUND, 10, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '0.0009876500000');
assert (decimal_to_precision ('0.00098765', ROUND, 1, SIGNIFICANT_DIGITS) === '0.001');
assert (decimal_to_precision ('0.00098765', ROUND, 10, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '0.0009876500000');

assert (Exchange::decimal_to_precision ('0.098765', ROUND, 1, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '0.1');
assert (decimal_to_precision ('0.098765', ROUND, 1, SIGNIFICANT_DIGITS, PAD_WITH_ZERO) === '0.1');

//-----------------------------------------------------------------------------
assert (decimal_to_precision ('0', ROUND, 0, SIGNIFICANT_DIGITS) === '0');

// ----------------------------------------------------------------------------
// testDecimalToPrecisionNegativeNumbers

assert (Exchange::decimal_to_precision ('-0.123456', TRUNCATE, 5, DECIMAL_PLACES) === '-0.12345');
assert (Exchange::decimal_to_precision ('-0.123456', ROUND, 5, DECIMAL_PLACES) === '-0.12346');
assert (decimal_to_precision ('-0.123456', TRUNCATE, 5, DECIMAL_PLACES) === '-0.12345');
assert (decimal_to_precision ('-0.123456', ROUND, 5, DECIMAL_PLACES) === '-0.12346');

// ----------------------------------------------------------------------------
// decimal_to_precision => without dot / trailing dot

assert (decimal_to_precision ('123', TRUNCATE, 0) === '123');

assert (decimal_to_precision ('123', TRUNCATE, 5, DECIMAL_PLACES) === '123');
assert (decimal_to_precision ('123', TRUNCATE, 5, DECIMAL_PLACES, PAD_WITH_ZERO) === '123.00000');

assert (decimal_to_precision ('123.', TRUNCATE, 0, DECIMAL_PLACES) === '123');
assert (decimal_to_precision ('123.', TRUNCATE, 5, DECIMAL_PLACES, PAD_WITH_ZERO) === '123.00000');

assert (decimal_to_precision ('0.', TRUNCATE, 0) === '0');
assert (decimal_to_precision ('0.', TRUNCATE, 5, DECIMAL_PLACES, PAD_WITH_ZERO) === '0.00000');

// ----------------------------------------------------------------------------
// decimal_to_precision => rounding for equidistant digits

assert (decimal_to_precision ('1.44', ROUND, 1, DECIMAL_PLACES) === '1.4');
assert (decimal_to_precision ('1.45', ROUND, 1, DECIMAL_PLACES) === '1.5');
assert (decimal_to_precision ('1.45', ROUND, 0, DECIMAL_PLACES) === '1'); // not 2

// ----------------------------------------------------------------------------
// testDecimalToPrecisionErrorHandling (todo)
//
// throws (() =>
// decimal_to_precision ('123456.789', TRUNCATE, -2, DECIMAL_PLACES),
// 'negative precision is not yet supported')
//
// throws (() =>
// decimal_to_precision ('foo'),
// "invalid number (contains an illegal character 'f')")
25 changes: 19 additions & 6 deletions python/ccxt/base/decimal_to_precision.py
Expand Up @@ -32,22 +32,30 @@ def decimal_to_precision(n, rounding_mode=ROUND, precision=None, counting_mode=D
assert counting_mode in [DECIMAL_PLACES, SIGNIFICANT_DIGITS]
assert padding_mode in [NO_PADDING, PAD_WITH_ZERO]

context = decimal.getcontext()

precision = min(context.prec - 2, precision)

print('------------')
print(precision)

# all default except decimal.Underflow (raised when a number is rounded to zero)
decimal.getcontext().traps[decimal.Underflow] = True
context.traps[decimal.Underflow] = True

dec = decimal.Decimal(n)
string = str(dec)

def quant(x):
def power_of_10(x):
return decimal.Decimal('10') ** (-x)

if rounding_mode == ROUND:
if counting_mode == DECIMAL_PLACES:
precise = str(dec.quantize(quant(precision))) # ROUND_HALF_EVEN is default context
precise = str(dec.quantize(power_of_10(precision))) # ROUND_HALF_EVEN is default context
elif counting_mode == SIGNIFICANT_DIGITS:
q = precision - dec.adjusted() - 1
sigfig = quant(q)
sigfig = power_of_10(q)
if q < 0:
print(q, sigfig, precision, string[:precision])
below = sigfig * decimal.Decimal(string[:precision])
above = below + sigfig
precise = str(min((below, above), key=lambda x: abs(x - dec)))
Expand All @@ -64,10 +72,15 @@ def quant(x):
dot = string.index('.') if '.' in string else 0
start = dot - dec.adjusted()
end = start + precision
# print(dec.adjusted())
# print(start)
# print(end)
# need to clarify these conditionals
if dot >= end:
end -= 1
if dec.adjusted() < 0:
end += 1
# if this is a negative exponent
# if dec.adjusted() < 0:
# end += 1
precise = string[:end].ljust(dot, '0')

if '.' == precise[-1]:
Expand Down

0 comments on commit 0480db2

Please sign in to comment.