From 6ed4581f545069488446682ee9b052798626327d Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 13 Jun 2017 13:36:56 +1000 Subject: py/formatfloat: Fix number of digits and exponent sign when rounding. This patch fixes 2 things when printing a floating-point number that requires rounding up of the mantissa: - retain the correct precision; eg 0.99 becomes 1.0, not 1.00 - if the exponent goes from -1 to 0 then render it as +0, not -0 --- tests/float/string_format_modulo.py | 3 +++ tests/float/string_format_modulo3.py | 3 +-- tests/float/string_format_modulo3.py.exp | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'tests/float') diff --git a/tests/float/string_format_modulo.py b/tests/float/string_format_modulo.py index 03c8dd00a..aea534247 100644 --- a/tests/float/string_format_modulo.py +++ b/tests/float/string_format_modulo.py @@ -44,3 +44,6 @@ print(('%.40g' % 1e-3)[:2]) print(('%.40g' % 1e-4)[:2]) print("%.0g" % 1) # 0 precision 'g' + +print('%.1e' % 9.99) # round up with positive exponent +print('%.1e' % 0.999) # round up with negative exponent diff --git a/tests/float/string_format_modulo3.py b/tests/float/string_format_modulo3.py index 563964786..5d26f2575 100644 --- a/tests/float/string_format_modulo3.py +++ b/tests/float/string_format_modulo3.py @@ -1,4 +1,3 @@ # uPy and CPython outputs differ for the following print("%.1g" % -9.9) # round up 'g' with '-' sign -print("%.1e" % 9.99) # round up with positive exponent -print("%.1e" % 0.999) # round up with negative exponent +print("%.2g" % 99.9) # round up diff --git a/tests/float/string_format_modulo3.py.exp b/tests/float/string_format_modulo3.py.exp index b158c7d7f..71432b340 100644 --- a/tests/float/string_format_modulo3.py.exp +++ b/tests/float/string_format_modulo3.py.exp @@ -1,3 +1,2 @@ -10 -1.00e+01 -1.00e-00 +100 -- cgit v1.2.3 From 6b8b56f8596d3dde544a72d037e9feddd9f70938 Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 4 Jul 2017 02:15:11 +1000 Subject: py/modmath: Check for zero division in log with 2 args. --- py/modmath.c | 2 ++ tests/float/math_fun.py | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'tests/float') diff --git a/py/modmath.c b/py/modmath.c index 10713234c..d5d135fc1 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -168,6 +168,8 @@ STATIC mp_obj_t mp_math_log(size_t n_args, const mp_obj_t *args) { mp_float_t base = mp_obj_get_float(args[1]); if (base <= (mp_float_t)0.0) { math_error(); + } else if (base == (mp_float_t)1.0) { + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } return mp_obj_new_float(l / MICROPY_FLOAT_C_FUN(log)(base)); } diff --git a/tests/float/math_fun.py b/tests/float/math_fun.py index 80d20bd8a..2835b9bfb 100644 --- a/tests/float/math_fun.py +++ b/tests/float/math_fun.py @@ -51,7 +51,7 @@ binary_functions = [('copysign', copysign, [(23., 42.), (-23., 42.), (23., -42.) ('atan2', atan2, ((1., 0.), (0., 1.), (2., 0.5), (-3., 5.), (-3., -4.),)), ('fmod', fmod, ((1., 1.), (0., 1.), (2., 0.5), (-3., 5.), (-3., -4.),)), ('ldexp', ldexp, ((1., 0), (0., 1), (2., 2), (3., -2), (-3., -4),)), - ('log', log, ((2., 2.), (3., 2.), (4., 5.), (0., 1.), (1., 0.), (-1., 1.), (1., -1.))), + ('log', log, ((2., 2.), (3., 2.), (4., 5.), (0., 1.), (1., 0.), (-1., 1.), (1., -1.), (2., 1.))), ] for function_name, function, test_vals in binary_functions: @@ -59,5 +59,5 @@ for function_name, function, test_vals in binary_functions: for value1, value2 in test_vals: try: print("{:.5g}".format(function(value1, value2))) - except ValueError as e: - print(str(e)) + except (ValueError, ZeroDivisionError) as e: + print(type(e)) -- cgit v1.2.3 From 04552ff71b6c722b21597d93481f024c72457cef Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 25 Jul 2017 11:49:22 +1000 Subject: py: Implement raising a big-int to a negative power. Before this patch raising a big-int to a negative power would just return 0. Now it returns a floating-point number with the correct value. --- py/mpz.c | 4 ---- py/mpz.h | 1 + py/objint_longlong.c | 7 +++++++ py/objint_mpz.c | 7 +++++++ tests/float/int_big_float.py | 4 ++++ 5 files changed, 19 insertions(+), 4 deletions(-) (limited to 'tests/float') diff --git a/py/mpz.c b/py/mpz.c index 80473df88..f58e262e2 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -946,10 +946,6 @@ bool mpz_is_pos(const mpz_t *z) { return z->len > 0 && z->neg == 0; } -bool mpz_is_neg(const mpz_t *z) { - return z->len > 0 && z->neg != 0; -} - bool mpz_is_odd(const mpz_t *z) { return z->len > 0 && (z->dig[0] & 1) != 0; } diff --git a/py/mpz.h b/py/mpz.h index 2ff404ffa..55967cc4c 100644 --- a/py/mpz.h +++ b/py/mpz.h @@ -112,6 +112,7 @@ size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigne void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf); static inline bool mpz_is_zero(const mpz_t *z) { return z->len == 0; } +static inline bool mpz_is_neg(const mpz_t *z) { return z->len != 0 && z->neg != 0; } int mpz_cmp(const mpz_t *lhs, const mpz_t *rhs); void mpz_abs_inpl(mpz_t *dest, const mpz_t *z); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index eb80407bc..1d184a7dc 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -191,6 +191,13 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: { + if (rhs_val < 0) { + #if MICROPY_PY_BUILTINS_FLOAT + return mp_obj_float_binary_op(op, lhs_val, rhs_in); + #else + mp_raise_ValueError("negative power with no float support"); + #endif + } long long ans = 1; while (rhs_val > 0) { if (rhs_val & 1) { diff --git a/py/objint_mpz.c b/py/objint_mpz.c index d818b6f40..26492aab4 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -290,6 +290,13 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_POWER: case MP_BINARY_OP_INPLACE_POWER: + if (mpz_is_neg(zrhs)) { + #if MICROPY_PY_BUILTINS_FLOAT + return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in); + #else + mp_raise_ValueError("negative power with no float support"); + #endif + } mpz_pow_inpl(&res->mpz, zlhs, zrhs); break; diff --git a/tests/float/int_big_float.py b/tests/float/int_big_float.py index b1a26ca73..0bd166218 100644 --- a/tests/float/int_big_float.py +++ b/tests/float/int_big_float.py @@ -18,6 +18,10 @@ print("%.5g" % (i / 1.2)) # this should delegate to complex print("%.5g" % (i * 1.2j).imag) +# negative power should produce float +print("%.5g" % (i ** -1)) +print("%.5g" % ((2 + i - i) ** -3)) + try: i / 0 except ZeroDivisionError: -- cgit v1.2.3