Browse Source

Fix String::num_real and String test cases when compiling with doubles

Aaron Franke 4 years ago
parent
commit
5d03c0e0b6
2 changed files with 27 additions and 10 deletions
  1. 16 9
      core/string/ustring.cpp
  2. 11 1
      tests/test_string.h

+ 16 - 9
core/string/ustring.cpp

@@ -1551,19 +1551,21 @@ String String::num_real(double p_num, bool p_trailing) {
 
 
 	bool neg = p_num < 0;
 	bool neg = p_num < 0;
 	p_num = ABS(p_num);
 	p_num = ABS(p_num);
-	int intn = (int)p_num;
+	int64_t intn = (int64_t)p_num;
 
 
 	// Decimal part.
 	// Decimal part.
 
 
 	if (intn != p_num) {
 	if (intn != p_num) {
-		double dec = p_num - (double)(intn);
+		double dec = p_num - (double)intn;
 
 
 		int digit = 0;
 		int digit = 0;
 
 
-#if 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.
@@ -1575,16 +1577,21 @@ String String::num_real(double p_num, bool p_trailing) {
 			decimals = MAX_DECIMALS;
 			decimals = MAX_DECIMALS;
 		}
 		}
 
 
-		int dec_int = 0;
-		int dec_max = 0;
+		// 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) {
 		while (true) {
 			dec *= 10.0;
 			dec *= 10.0;
-			dec_int = dec_int * 10 + (int)dec % 10;
+			dec_int = dec_int * 10 + (int64_t)dec % 10;
 			dec_max = dec_max * 10 + 9;
 			dec_max = dec_max * 10 + 9;
 			digit++;
 			digit++;
 
 
-			if ((dec - (double)((int)dec)) < 1e-6) {
+			if ((dec - (double)(int64_t)(dec * check_multiplier)) < tolerance) {
 				break;
 				break;
 			}
 			}
 
 
@@ -1594,7 +1601,7 @@ String String::num_real(double p_num, bool p_trailing) {
 		}
 		}
 
 
 		dec *= 10;
 		dec *= 10;
-		int last = (int)dec % 10;
+		int last = (int64_t)dec % 10;
 
 
 		if (last > 5) {
 		if (last > 5) {
 			if (dec_int == dec_max) {
 			if (dec_int == dec_max) {
@@ -3555,7 +3562,7 @@ String String::strip_edges(bool left, bool right) const {
 	}
 	}
 
 
 	if (right) {
 	if (right) {
-		for (int i = (int)(len - 1); i >= 0; i--) {
+		for (int i = len - 1; i >= 0; i--) {
 			if (operator[](i) <= 32) {
 			if (operator[](i) <= 32) {
 				end--;
 				end--;
 			} else {
 			} else {

+ 11 - 1
tests/test_string.h

@@ -355,13 +355,23 @@ TEST_CASE("[String] Number to string") {
 	CHECK(String::num(-0.0) == "-0"); // Includes sign even for zero.
 	CHECK(String::num(-0.0) == "-0"); // Includes sign even for zero.
 	CHECK(String::num(3.141593) == "3.141593");
 	CHECK(String::num(3.141593) == "3.141593");
 	CHECK(String::num(3.141593, 3) == "3.142");
 	CHECK(String::num(3.141593, 3) == "3.142");
-	CHECK(String::num_real(3.141593) == "3.141593");
 	CHECK(String::num_scientific(30000000) == "3e+07");
 	CHECK(String::num_scientific(30000000) == "3e+07");
 	CHECK(String::num_int64(3141593) == "3141593");
 	CHECK(String::num_int64(3141593) == "3141593");
 	CHECK(String::num_int64(0xA141593, 16) == "a141593");
 	CHECK(String::num_int64(0xA141593, 16) == "a141593");
 	CHECK(String::num_int64(0xA141593, 16, true) == "A141593");
 	CHECK(String::num_int64(0xA141593, 16, true) == "A141593");
 	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.
+	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).");
+#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.");
+#endif // REAL_T_IS_DOUBLE
+
 	// Checks doubles with many decimal places.
 	// Checks doubles with many decimal places.
 	CHECK(String::num(0.0000012345432123454321, -1) == "0.00000123454321"); // -1 uses 14 as sane default.
 	CHECK(String::num(0.0000012345432123454321, -1) == "0.00000123454321"); // -1 uses 14 as sane default.
 	CHECK(String::num(0.0000012345432123454321) == "0.00000123454321"); // -1 is the default value.
 	CHECK(String::num(0.0000012345432123454321) == "0.00000123454321"); // -1 is the default value.