Browse Source

Merge pull request #56809 from aaronfranke/replace-num-real

Rémi Verschelde 3 years ago
parent
commit
24f8a5979c

+ 11 - 102
core/string/ustring.cpp

@@ -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) {
-	if (Math::is_nan(p_num)) {
-		return "nan";
-	}
-
-	if (Math::is_inf(p_num)) {
-		if (signbit(p_num)) {
-			return "-inf";
+	if (p_num == (double)(int64_t)p_num) {
+		if (p_trailing) {
+			return num_int64((int64_t)p_num) + ".0";
 		} 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
-		int decimals = 14;
-		double tolerance = 1e-14;
+	int decimals = 14;
 #else
-		int decimals = 6;
-		double tolerance = 1e-6;
+	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;
-		}
-
-		// 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 = "";
+	// 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 (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;
+	return num(p_num, decimals);
 }
 
 String String::num_scientific(double p_num) {

+ 19 - 0
tests/core/math/test_vector2.h

@@ -246,6 +246,25 @@ TEST_CASE("[Vector2] Operators") {
 	CHECK_MESSAGE(
 			Vector2(Vector2i(1, 2)) == Vector2(1, 2),
 			"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") {

+ 19 - 0
tests/core/math/test_vector3.h

@@ -271,6 +271,25 @@ TEST_CASE("[Vector3] Operators") {
 	CHECK_MESSAGE(
 			Vector3(Vector3i(1, 2, 3)) == Vector3(1, 2, 3),
 			"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") {

+ 7 - 1
tests/core/string/test_string.h

@@ -355,11 +355,17 @@ TEST_CASE("[String] Number to string") {
 	CHECK(String::num(42.100023, 4) == "42.1"); // No trailing zeros.
 
 	// 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.141) == "3.141"); // No trailing zeros.
 #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(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
 	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.");