make float more precise

This commit is contained in:
BLUELOVETH 2023-06-01 03:25:57 +08:00
parent d350eb184b
commit 1a8fef1014
3 changed files with 23 additions and 13 deletions

View File

@ -101,6 +101,10 @@ struct NumberTraits<4> {
static int_t stoi(Args&&... args) { return std::stoi(std::forward<Args>(args)...); }
template<typename... Args>
static float_t stof(Args&&... args) { return std::stof(std::forward<Args>(args)...); }
static constexpr int_t c0 = 0b00000000011111111111111111111100;
static constexpr int_t c1 = 0b11111111111111111111111111111100;
static constexpr int_t c2 = 0b00000000000000000000000000000011;
};
template <>
@ -112,6 +116,10 @@ struct NumberTraits<8> {
static int_t stoi(Args&&... args) { return std::stoll(std::forward<Args>(args)...); }
template<typename... Args>
static float_t stof(Args&&... args) { return std::stod(std::forward<Args>(args)...); }
static constexpr int_t c0 = 0b0000000000001111111111111111111111111111111111111111111111111100;
static constexpr int_t c1 = 0b1111111111111111111111111111111111111111111111111111111111111100;
static constexpr int_t c2 = 0b0000000000000000000000000000000000000000000000000000000000000011;
};
using Number = NumberTraits<sizeof(void*)>;

View File

@ -343,7 +343,7 @@ inline void init_builtins(VM* _vm) {
f64 val = _CAST(f64, obj);
if(std::isinf(val) || std::isnan(val)) return VAR(std::to_string(val));
std::stringstream ss;
ss << std::setprecision(std::numeric_limits<f64>::max_digits10-1-2) << val;
ss << std::setprecision(std::numeric_limits<f64>::max_digits10-2) << val;
std::string s = ss.str();
if(std::all_of(s.begin()+1, s.end(), isdigit)) s += ".0";
return VAR(s);

View File

@ -709,24 +709,20 @@ PY_CAST_INT(unsigned long long)
template<> inline float py_cast<float>(VM* vm, PyObject* obj){
vm->check_float(obj);
i64 bits = BITS(obj);
bits = (bits >> 2) << 2;
i64 bits = BITS(obj) & Number::c1;
return BitsCvt(bits)._float;
}
template<> inline float _py_cast<float>(VM* vm, PyObject* obj){
i64 bits = BITS(obj);
bits = (bits >> 2) << 2;
i64 bits = BITS(obj) & Number::c1;
return BitsCvt(bits)._float;
}
template<> inline double py_cast<double>(VM* vm, PyObject* obj){
vm->check_float(obj);
i64 bits = BITS(obj);
bits = (bits >> 2) << 2;
i64 bits = BITS(obj) & Number::c1;
return BitsCvt(bits)._float;
}
template<> inline double _py_cast<double>(VM* vm, PyObject* obj){
i64 bits = BITS(obj);
bits = (bits >> 2) << 2;
i64 bits = BITS(obj) & Number::c1;
return BitsCvt(bits)._float;
}
@ -752,11 +748,17 @@ PY_VAR_INT(unsigned int)
PY_VAR_INT(unsigned long)
PY_VAR_INT(unsigned long long)
#define PY_VAR_FLOAT(T) \
#define PY_VAR_FLOAT(T) \
inline PyObject* py_var(VM* vm, T _val){ \
f64 val = static_cast<f64>(_val); \
i64 bits = BitsCvt(val)._int; \
bits = (bits >> 2) << 2; \
BitsCvt val(static_cast<f64>(_val)); \
i64 bits = val._int & Number::c1; \
i64 tail = val._int & Number::c2; \
if(tail == 0b10){ \
if((bits&Number::c0)!=Number::c0 && (bits&0b100)) bits += 0b100; \
}else if(tail == 0b11){ \
if((bits&Number::c0)!=Number::c0) bits += 0b100; \
} \
bits |= 0b10; \
return reinterpret_cast<PyObject*>(bits); \
}