Skip to content

Commit 12033df

Browse files
committed
py: Partially fix float to int conversion.
This fixes conversion when float type has more mantissa bits than small int, and float value has small exponent. This is for example the case of 32-bit platform using doubles, and converting value of time.time(). Conversion of floats with larg exponnet is still not handled correctly.
1 parent e3fa827 commit 12033df

File tree

5 files changed

+31
-1
lines changed

5 files changed

+31
-1
lines changed

py/obj.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value);
399399
mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base);
400400
mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception)
401401
mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception)
402+
mp_obj_t mp_obj_new_int_from_float(mp_float_t val);
402403
mp_obj_t mp_obj_new_str(const char* data, mp_uint_t len, bool make_qstr_if_not_already);
403404
mp_obj_t mp_obj_new_bytes(const byte* data, mp_uint_t len);
404405
mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items);

py/objint.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
6565
return mp_parse_num_integer(s, l, 0);
6666
#if MICROPY_PY_BUILTINS_FLOAT
6767
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
68-
return MP_OBJ_NEW_SMALL_INT((MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0]))));
68+
return mp_obj_new_int_from_float(mp_obj_float_get(args[0]));
6969
#endif
7070
} else {
7171
// try to convert to small int (eg from bool)

py/objint_longlong.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
#include "runtime0.h"
4141
#include "runtime.h"
4242

43+
#if MICROPY_PY_BUILTINS_FLOAT
44+
#include <math.h>
45+
#endif
46+
4347
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
4448

4549
// Python3 no longer has "l" suffix for long ints. We allow to use it
@@ -187,6 +191,14 @@ mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
187191
return o;
188192
}
189193

194+
#if MICROPY_PY_BUILTINS_FLOAT
195+
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
196+
// TODO raise an exception if the unsigned long long won't fit
197+
long long i = MICROPY_FLOAT_C_FUN(trunc)(val);
198+
return mp_obj_new_int_from_ll(i);
199+
}
200+
#endif
201+
190202
mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) {
191203
// TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated
192204
// TODO check overflow

py/objint_mpz.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
#include "runtime0.h"
4242
#include "runtime.h"
4343

44+
#if MICROPY_PY_BUILTINS_FLOAT
45+
#include <math.h>
46+
#endif
47+
4448
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
4549

4650
#if MICROPY_PY_SYS_MAXSIZE
@@ -298,6 +302,14 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
298302
return mp_obj_new_int_from_ll(value);
299303
}
300304

305+
#if MICROPY_PY_BUILTINS_FLOAT
306+
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
307+
// TODO: This doesn't handle numbers with large exponent
308+
long long i = MICROPY_FLOAT_C_FUN(trunc)(val);
309+
return mp_obj_new_int_from_ll(i);
310+
}
311+
#endif
312+
301313
mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) {
302314
mp_obj_int_t *o = mp_obj_int_new_mpz();
303315
mp_uint_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);

tests/float/float2int.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# This case occurs with time.time() values
2+
print(int(1418774543.))
3+
4+
# TODO: General case with large exponent
5+
#print(int(2.**100))

0 commit comments

Comments
 (0)