summaryrefslogtreecommitdiff
path: root/core/string
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2021-08-17 11:43:11 +0200
committerRémi Verschelde <rverschelde@gmail.com>2021-08-18 00:48:03 +0200
commit066dbc2f0c705f963617f45c2e0b352ccf652c9c (patch)
tree478b0a78a1c10c14d3de1c2cb56055adac04bbf7 /core/string
parentc4e03672e8989c58d38509971d097496c790fc7d (diff)
String: Fix default decimals truncation in num and num_real
Fixes undefined behavior, and fixes the logic for negative powers of ten. Fixes #51764. Adds tests to validate the changes and prevent regressions. Adds docs for `String.num`.
Diffstat (limited to 'core/string')
-rw-r--r--core/string/ustring.cpp27
1 files changed, 20 insertions, 7 deletions
diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp
index 2fdf6e84e5..d2d563c5dc 100644
--- a/core/string/ustring.cpp
+++ b/core/string/ustring.cpp
@@ -1396,7 +1396,13 @@ String String::num(double p_num, int p_decimals) {
#ifndef NO_USE_STDLIB
if (p_decimals < 0) {
- p_decimals = 14 - (int)floor(log10(p_num));
+ p_decimals = 14;
+ const double abs_num = ABS(p_num);
+ if (abs_num > 10) {
+ // We want to align the digits to the above sane default, so we only
+ // need to subtract log10 for numbers with a positive power of ten.
+ p_decimals -= (int)floor(log10(abs_num));
+ }
}
if (p_decimals > MAX_DECIMALS) {
p_decimals = MAX_DECIMALS;
@@ -1625,24 +1631,31 @@ String String::num_real(double p_num, bool p_trailing) {
String s;
String sd;
- /* integer part */
+
+ // Integer part.
bool neg = p_num < 0;
p_num = ABS(p_num);
int intn = (int)p_num;
- /* decimal part */
+ // Decimal part.
- if ((int)p_num != p_num) {
- double dec = p_num - (double)((int)p_num);
+ if (intn != p_num) {
+ double dec = p_num - (double)(intn);
int digit = 0;
#if REAL_T_IS_DOUBLE
- int decimals = 14 - (int)floor(log10(p_num));
+ int decimals = 14;
#else
- int decimals = 6 - (int)floor(log10(p_num));
+ int decimals = 6;
#endif
+ // We want to align the digits to the above sane default, so we only
+ // need to subtract log10 for numbers with a positive power of ten.
+ if (p_num > 10) {
+ decimals -= (int)floor(log10(p_num));
+ }
+
if (decimals > MAX_DECIMALS) {
decimals = MAX_DECIMALS;
}