Replace String::num_real code with a wrapper around String::num
This commit is contained in:
parent
c1e78f749e
commit
13939734e0
@ -1527,115 +1527,24 @@ String String::num_uint64(uint64_t p_num, int base, bool capitalize_hex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String String::num_real(double p_num, bool p_trailing) {
|
String String::num_real(double p_num, bool p_trailing) {
|
||||||
if (Math::is_nan(p_num)) {
|
if (p_num == (double)(int64_t)p_num) {
|
||||||
return "nan";
|
if (p_trailing) {
|
||||||
}
|
return num_int64((int64_t)p_num) + ".0";
|
||||||
|
|
||||||
if (Math::is_inf(p_num)) {
|
|
||||||
if (signbit(p_num)) {
|
|
||||||
return "-inf";
|
|
||||||
} else {
|
} else {
|
||||||
return "inf";
|
return num_int64((int64_t)p_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String s;
|
|
||||||
String sd;
|
|
||||||
|
|
||||||
// Integer part.
|
|
||||||
|
|
||||||
bool neg = p_num < 0;
|
|
||||||
p_num = ABS(p_num);
|
|
||||||
int64_t intn = (int64_t)p_num;
|
|
||||||
|
|
||||||
// Decimal part.
|
|
||||||
|
|
||||||
if (intn != p_num) {
|
|
||||||
double dec = p_num - (double)intn;
|
|
||||||
|
|
||||||
int digit = 0;
|
|
||||||
|
|
||||||
#ifdef REAL_T_IS_DOUBLE
|
#ifdef REAL_T_IS_DOUBLE
|
||||||
int decimals = 14;
|
int decimals = 14;
|
||||||
double tolerance = 1e-14;
|
|
||||||
#else
|
#else
|
||||||
int decimals = 6;
|
int decimals = 6;
|
||||||
double tolerance = 1e-6;
|
|
||||||
#endif
|
#endif
|
||||||
// We want to align the digits to the above sane default, so we only
|
// 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.
|
// need to subtract log10 for numbers with a positive power of ten.
|
||||||
if (p_num > 10) {
|
if (p_num > 10) {
|
||||||
decimals -= (int)floor(log10(p_num));
|
decimals -= (int)floor(log10(p_num));
|
||||||
}
|
}
|
||||||
|
return num(p_num, decimals);
|
||||||
if (decimals > MAX_DECIMALS) {
|
|
||||||
decimals = MAX_DECIMALS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case the value ends up ending in "99999", we want to add a
|
|
||||||
// tiny bit to the value we're checking when deciding when to stop,
|
|
||||||
// so we multiply by slightly above 1 (1 + 1e-7 or 1e-15).
|
|
||||||
double check_multiplier = 1 + tolerance / 10;
|
|
||||||
|
|
||||||
int64_t dec_int = 0;
|
|
||||||
int64_t dec_max = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
dec *= 10.0;
|
|
||||||
dec_int = dec_int * 10 + (int64_t)dec % 10;
|
|
||||||
dec_max = dec_max * 10 + 9;
|
|
||||||
digit++;
|
|
||||||
|
|
||||||
if ((dec - (double)(int64_t)(dec * check_multiplier)) < tolerance) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (digit == decimals) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dec *= 10;
|
|
||||||
int last = (int64_t)dec % 10;
|
|
||||||
|
|
||||||
if (last > 5) {
|
|
||||||
if (dec_int == dec_max) {
|
|
||||||
dec_int = 0;
|
|
||||||
intn++;
|
|
||||||
} else {
|
|
||||||
dec_int++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String decimal;
|
|
||||||
for (int i = 0; i < digit; i++) {
|
|
||||||
char num[2] = { 0, 0 };
|
|
||||||
num[0] = '0' + dec_int % 10;
|
|
||||||
decimal = num + decimal;
|
|
||||||
dec_int /= 10;
|
|
||||||
}
|
|
||||||
sd = '.' + decimal;
|
|
||||||
} else if (p_trailing) {
|
|
||||||
sd = ".0";
|
|
||||||
} else {
|
|
||||||
sd = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intn == 0) {
|
|
||||||
s = "0";
|
|
||||||
} else {
|
|
||||||
while (intn) {
|
|
||||||
char32_t num = '0' + (intn % 10);
|
|
||||||
intn /= 10;
|
|
||||||
s = num + s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s = s + sd;
|
|
||||||
if (neg) {
|
|
||||||
s = "-" + s;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String String::num_scientific(double p_num) {
|
String String::num_scientific(double p_num) {
|
||||||
|
@ -246,6 +246,25 @@ TEST_CASE("[Vector2] Operators") {
|
|||||||
CHECK_MESSAGE(
|
CHECK_MESSAGE(
|
||||||
Vector2(Vector2i(1, 2)) == Vector2(1, 2),
|
Vector2(Vector2i(1, 2)) == Vector2(1, 2),
|
||||||
"Vector2 constructed from Vector2i should work as expected.");
|
"Vector2 constructed from Vector2i should work as expected.");
|
||||||
|
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)decimal1) == "(2.3, 4.9)",
|
||||||
|
"Vector2 cast to String should work as expected.");
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)decimal2) == "(1.2, 3.4)",
|
||||||
|
"Vector2 cast to String should work as expected.");
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)Vector2(9.8, 9.9)) == "(9.8, 9.9)",
|
||||||
|
"Vector2 cast to String should work as expected.");
|
||||||
|
#ifdef REAL_T_IS_DOUBLE
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)Vector2(Math_PI, Math_TAU)) == "(3.14159265358979, 6.28318530717959)",
|
||||||
|
"Vector2 cast to String should print the correct amount of digits for real_t = double.");
|
||||||
|
#else
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)Vector2(Math_PI, Math_TAU)) == "(3.141593, 6.283185)",
|
||||||
|
"Vector2 cast to String should print the correct amount of digits for real_t = float.");
|
||||||
|
#endif // REAL_T_IS_DOUBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[Vector2] Other methods") {
|
TEST_CASE("[Vector2] Other methods") {
|
||||||
|
@ -271,6 +271,25 @@ TEST_CASE("[Vector3] Operators") {
|
|||||||
CHECK_MESSAGE(
|
CHECK_MESSAGE(
|
||||||
Vector3(Vector3i(1, 2, 3)) == Vector3(1, 2, 3),
|
Vector3(Vector3i(1, 2, 3)) == Vector3(1, 2, 3),
|
||||||
"Vector3 constructed from Vector3i should work as expected.");
|
"Vector3 constructed from Vector3i should work as expected.");
|
||||||
|
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)decimal1) == "(2.3, 4.9, 7.8)",
|
||||||
|
"Vector3 cast to String should work as expected.");
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)decimal2) == "(1.2, 3.4, 5.6)",
|
||||||
|
"Vector3 cast to String should work as expected.");
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)Vector3(9.7, 9.8, 9.9)) == "(9.7, 9.8, 9.9)",
|
||||||
|
"Vector3 cast to String should work as expected.");
|
||||||
|
#ifdef REAL_T_IS_DOUBLE
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)Vector3(Math_E, Math_SQRT2, Math_SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888)",
|
||||||
|
"Vector3 cast to String should print the correct amount of digits for real_t = double.");
|
||||||
|
#else
|
||||||
|
CHECK_MESSAGE(
|
||||||
|
((String)Vector3(Math_E, Math_SQRT2, Math_SQRT3)) == "(2.718282, 1.414214, 1.732051)",
|
||||||
|
"Vector3 cast to String should print the correct amount of digits for real_t = float.");
|
||||||
|
#endif // REAL_T_IS_DOUBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("[Vector3] Other methods") {
|
TEST_CASE("[Vector3] Other methods") {
|
||||||
|
@ -355,11 +355,17 @@ TEST_CASE("[String] Number to string") {
|
|||||||
CHECK(String::num(42.100023, 4) == "42.1"); // No trailing zeros.
|
CHECK(String::num(42.100023, 4) == "42.1"); // No trailing zeros.
|
||||||
|
|
||||||
// String::num_real tests.
|
// String::num_real tests.
|
||||||
|
CHECK(String::num_real(1.0) == "1.0");
|
||||||
|
CHECK(String::num_real(1.0, false) == "1");
|
||||||
|
CHECK(String::num_real(9.9) == "9.9");
|
||||||
|
CHECK(String::num_real(9.99) == "9.99");
|
||||||
|
CHECK(String::num_real(9.999) == "9.999");
|
||||||
|
CHECK(String::num_real(9.9999) == "9.9999");
|
||||||
CHECK(String::num_real(3.141593) == "3.141593");
|
CHECK(String::num_real(3.141593) == "3.141593");
|
||||||
CHECK(String::num_real(3.141) == "3.141"); // No trailing zeros.
|
CHECK(String::num_real(3.141) == "3.141"); // No trailing zeros.
|
||||||
#ifdef REAL_T_IS_DOUBLE
|
#ifdef REAL_T_IS_DOUBLE
|
||||||
CHECK_MESSAGE(String::num_real(Math_PI) == "3.14159265358979", "Prints the appropriate amount of digits for real_t = double.");
|
CHECK_MESSAGE(String::num_real(Math_PI) == "3.14159265358979", "Prints the appropriate amount of digits for real_t = double.");
|
||||||
CHECK_MESSAGE(String::num_real(3.1415f) == "3.14149999618530", "Prints more digits of 32-bit float when real_t = double (ones that would be reliable for double).");
|
CHECK_MESSAGE(String::num_real(3.1415f) == "3.1414999961853", "Prints more digits of 32-bit float when real_t = double (ones that would be reliable for double) and no trailing zero.");
|
||||||
#else
|
#else
|
||||||
CHECK_MESSAGE(String::num_real(Math_PI) == "3.141593", "Prints the appropriate amount of digits for real_t = float.");
|
CHECK_MESSAGE(String::num_real(Math_PI) == "3.141593", "Prints the appropriate amount of digits for real_t = float.");
|
||||||
CHECK_MESSAGE(String::num_real(3.1415f) == "3.1415", "Prints only reliable digits of 32-bit float when real_t = float.");
|
CHECK_MESSAGE(String::num_real(3.1415f) == "3.1415", "Prints only reliable digits of 32-bit float when real_t = float.");
|
||||||
|
Loading…
Reference in New Issue
Block a user