Increase String::num default decimal precision
Fixes #34541 Renamed MAX_DIGITS to MAX_DECIMALS, since it only changes the amount of digits after the decimal point. Increased MAX_DECIMALS to 32, and made String::num use MAX_DECIMALS consistently. If -1 is passed as decimal precision to String::num, it now gets changed to the correct precision based on the number's magnitude, instead of using printf default(which is 6) String::num_real also calculates the correct precision now. Also made the types used in floating-point math more consistent in a few places.
This commit is contained in:
parent
b63f9b5961
commit
09a905ca80
|
@ -2415,12 +2415,12 @@ Variant JSONParseResult::get_result() const {
|
|||
}
|
||||
|
||||
void _JSON::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("print", "value", "indent", "sort_keys"), &_JSON::print, DEFVAL(String()), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("print", "value", "indent", "sort_keys", "full_precision"), &_JSON::print, DEFVAL(String()), DEFVAL(false), DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("parse", "json"), &_JSON::parse);
|
||||
}
|
||||
|
||||
String _JSON::print(const Variant &p_value, const String &p_indent, bool p_sort_keys) {
|
||||
return JSON::print(p_value, p_indent, p_sort_keys);
|
||||
String _JSON::print(const Variant &p_value, const String &p_indent, bool p_sort_keys, bool p_full_precision) {
|
||||
return JSON::print(p_value, p_indent, p_sort_keys, p_full_precision);
|
||||
}
|
||||
|
||||
Ref<JSONParseResult> _JSON::parse(const String &p_json) {
|
||||
|
|
|
@ -705,7 +705,7 @@ protected:
|
|||
public:
|
||||
static _JSON *get_singleton() { return singleton; }
|
||||
|
||||
String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false);
|
||||
String print(const Variant &p_value, const String &p_indent = "", bool p_sort_keys = false, bool p_full_precision = false);
|
||||
Ref<JSONParseResult> parse(const String &p_json);
|
||||
|
||||
_JSON() { singleton = this; }
|
||||
|
|
|
@ -55,7 +55,7 @@ static String _make_indent(const String &p_indent, int p_size) {
|
|||
return indent_text;
|
||||
}
|
||||
|
||||
String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys) {
|
||||
String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, bool p_full_precision) {
|
||||
String colon = ":";
|
||||
String end_statement = "";
|
||||
|
||||
|
@ -71,8 +71,17 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
|
|||
return p_var.operator bool() ? "true" : "false";
|
||||
case Variant::INT:
|
||||
return itos(p_var);
|
||||
case Variant::FLOAT:
|
||||
return rtos(p_var);
|
||||
case Variant::FLOAT: {
|
||||
double num = p_var;
|
||||
if (p_full_precision) {
|
||||
// Store unreliable digits (17) instead of just reliable
|
||||
// digits (14) so that the value can be decoded exactly.
|
||||
return String::num(num, 17 - (int)floor(log10(num)));
|
||||
} else {
|
||||
// Store only reliable digits (14) by default.
|
||||
return String::num(num, 14 - (int)floor(log10(num)));
|
||||
}
|
||||
}
|
||||
case Variant::PACKED_INT32_ARRAY:
|
||||
case Variant::PACKED_INT64_ARRAY:
|
||||
case Variant::PACKED_FLOAT32_ARRAY:
|
||||
|
@ -121,8 +130,8 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
|
|||
}
|
||||
}
|
||||
|
||||
String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys) {
|
||||
return _print_var(p_var, p_indent, 0, p_sort_keys);
|
||||
String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys, bool p_full_precision) {
|
||||
return _print_var(p_var, p_indent, 0, p_sort_keys, p_full_precision);
|
||||
}
|
||||
|
||||
Error JSON::_get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) {
|
||||
|
|
|
@ -62,7 +62,7 @@ class JSON {
|
|||
|
||||
static const char *tk_name[TK_MAX];
|
||||
|
||||
static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys);
|
||||
static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, bool p_full_precision = false);
|
||||
|
||||
static Error _get_token(const char32_t *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
|
||||
static Error _parse_value(Variant &value, Token &token, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
|
||||
|
@ -70,7 +70,7 @@ class JSON {
|
|||
static Error _parse_object(Dictionary &object, const char32_t *p_str, int &index, int p_len, int &line, String &r_err_str);
|
||||
|
||||
public:
|
||||
static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true);
|
||||
static String print(const Variant &p_var, const String &p_indent = "", bool p_sort_keys = true, bool p_full_precision = false);
|
||||
static Error parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line);
|
||||
};
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#define snprintf _snprintf_s
|
||||
#endif
|
||||
|
||||
#define MAX_DIGITS 6
|
||||
#define MAX_DECIMALS 32
|
||||
#define UPPERCASE(m_c) (((m_c) >= 'a' && (m_c) <= 'z') ? ((m_c) - ('a' - 'A')) : (m_c))
|
||||
#define LOWERCASE(m_c) (((m_c) >= 'A' && (m_c) <= 'Z') ? ((m_c) + ('a' - 'A')) : (m_c))
|
||||
#define IS_DIGIT(m_d) ((m_d) >= '0' && (m_d) <= '9')
|
||||
|
@ -1379,8 +1379,11 @@ String String::num(double p_num, int p_decimals) {
|
|||
}
|
||||
#ifndef NO_USE_STDLIB
|
||||
|
||||
if (p_decimals > 16) {
|
||||
p_decimals = 16;
|
||||
if (p_decimals < 0) {
|
||||
p_decimals = 14 - (int)floor(log10(p_num));
|
||||
}
|
||||
if (p_decimals > MAX_DECIMALS) {
|
||||
p_decimals = MAX_DECIMALS;
|
||||
}
|
||||
|
||||
char fmt[7];
|
||||
|
@ -1391,7 +1394,6 @@ String String::num(double p_num, int p_decimals) {
|
|||
fmt[1] = 'l';
|
||||
fmt[2] = 'f';
|
||||
fmt[3] = 0;
|
||||
|
||||
} else if (p_decimals < 10) {
|
||||
fmt[2] = '0' + p_decimals;
|
||||
fmt[3] = 'l';
|
||||
|
@ -1458,8 +1460,9 @@ String String::num(double p_num, int p_decimals) {
|
|||
double dec = p_num - (double)((int)p_num);
|
||||
|
||||
int digit = 0;
|
||||
if (p_decimals > MAX_DIGITS)
|
||||
p_decimals = MAX_DIGITS;
|
||||
if (p_decimals > MAX_DECIMALS) {
|
||||
p_decimals = MAX_DECIMALS;
|
||||
}
|
||||
|
||||
int dec_int = 0;
|
||||
int dec_max = 0;
|
||||
|
@ -1471,16 +1474,18 @@ String String::num(double p_num, int p_decimals) {
|
|||
digit++;
|
||||
|
||||
if (p_decimals == -1) {
|
||||
if (digit == MAX_DIGITS) //no point in going to infinite
|
||||
if (digit == MAX_DECIMALS) { //no point in going to infinite
|
||||
break;
|
||||
}
|
||||
|
||||
if (dec - (double)((int)dec) < 1e-6) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (digit == p_decimals)
|
||||
if (digit == p_decimals) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
dec *= 10;
|
||||
int last = (int)dec % 10;
|
||||
|
@ -1616,7 +1621,15 @@ String String::num_real(double p_num) {
|
|||
double dec = p_num - (double)((int)p_num);
|
||||
|
||||
int digit = 0;
|
||||
int decimals = MAX_DIGITS;
|
||||
|
||||
#if REAL_T_IS_DOUBLE
|
||||
int decimals = 14 - (int)floor(log10(p_num));
|
||||
#else
|
||||
int decimals = 6 - (int)floor(log10(p_num));
|
||||
#endif
|
||||
if (decimals > MAX_DECIMALS) {
|
||||
decimals = MAX_DECIMALS;
|
||||
}
|
||||
|
||||
int dec_int = 0;
|
||||
int dec_max = 0;
|
||||
|
|
|
@ -27,9 +27,12 @@
|
|||
</argument>
|
||||
<argument index="2" name="sort_keys" type="bool" default="false">
|
||||
</argument>
|
||||
<argument index="3" name="full_precision" type="bool" default="false">
|
||||
</argument>
|
||||
<description>
|
||||
Converts a [Variant] var to JSON text and returns the result. Useful for serializing data to store or send over the network.
|
||||
[b]Note:[/b] The JSON specification does not define integer or float types, but only a [i]number[/i] type. Therefore, converting a Variant to JSON text will convert all numerical values to [float] types.
|
||||
[b]Note:[/b] If [code]full_precision[/code] is true, when printing floats, the unreliable digits are printed in addition to the reliable digits to guarantee exact decoding.
|
||||
Use [code]indent[/code] parameter to pretty print the output.
|
||||
[b]Example output:[/b]
|
||||
[codeblock]
|
||||
|
|
|
@ -240,10 +240,10 @@
|
|||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
<constant name="PI" value="3.141593">
|
||||
<constant name="PI" value="3.14159265358979">
|
||||
Constant that represents how many times the diameter of a circle fits around its perimeter. This is equivalent to [code]TAU / 2[/code].
|
||||
</constant>
|
||||
<constant name="TAU" value="6.283185">
|
||||
<constant name="TAU" value="6.28318530717959">
|
||||
The circle constant, the circumference of the unit circle in radians.
|
||||
</constant>
|
||||
<constant name="INF" value="inf">
|
||||
|
|
Loading…
Reference in New Issue