Use Grisu2 algorithm in String::num_scientific to fix serializing

This commit is contained in:
Aaron Franke
2024-11-01 02:02:09 -07:00
parent 4a44078451
commit 15de1d6c35
29 changed files with 1560 additions and 200 deletions

View File

@@ -546,7 +546,6 @@ TEST_CASE("[String] Number to string") {
CHECK(String::num(3.141593) == "3.141593");
CHECK(String::num(3.141593, 3) == "3.142");
CHECK(String::num(42.100023, 4) == "42.1"); // No trailing zeros.
CHECK(String::num_scientific(30000000) == "3e+07");
// String::num_int64 tests.
CHECK(String::num_int64(3141593) == "3141593");
@@ -567,6 +566,20 @@ TEST_CASE("[String] Number to string") {
CHECK(String::num_uint64(4294967295, 37) == ""); // Invalid base > 36.
ERR_PRINT_ON;
// String::num_scientific tests.
CHECK(String::num_scientific(30000000.0) == "30000000");
CHECK(String::num_scientific(1234567890.0) == "1234567890");
CHECK(String::num_scientific(3e100) == "3e+100");
CHECK(String::num_scientific(7e-100) == "7e-100");
CHECK(String::num_scientific(Math::TAU) == "6.283185307179586");
CHECK(String::num_scientific(Math::INF) == "inf");
CHECK(String::num_scientific(-Math::INF) == "-inf");
CHECK(String::num_scientific(Math::NaN) == "nan");
CHECK(String::num_scientific(2.0) == "2");
CHECK(String::num_scientific(1.0) == "1");
CHECK(String::num_scientific(0.0) == "0");
CHECK(String::num_scientific(-0.0) == "-0");
// String::num_real tests.
CHECK(String::num_real(1.0) == "1.0");
CHECK(String::num_real(1.0, false) == "1");

View File

@@ -101,7 +101,7 @@ TEST_CASE("[Variant] Writer and parser Variant::FLOAT") {
String a64_str;
VariantWriter::write_to_string(a64, a64_str);
CHECK_MESSAGE(a64_str == "1.79769e+308", "Writes in scientific notation.");
CHECK_MESSAGE(a64_str == "1.7976931348623157e+308", "Writes in scientific notation.");
CHECK_MESSAGE(a64_str != "inf", "Should not overflow.");
CHECK_MESSAGE(a64_str != "nan", "The result should be defined.");
@@ -115,7 +115,7 @@ TEST_CASE("[Variant] Writer and parser Variant::FLOAT") {
VariantParser::parse(&bss, variant_parsed, errs, line);
float_parsed = variant_parsed;
// Loses precision, but that's alright.
CHECK_MESSAGE(float_parsed == 1.79769e+308, "Should parse back.");
CHECK_MESSAGE(float_parsed == 1.797693134862315708145274237317e+308, "Should parse back.");
// Approximation of Googol with a double-precision float.
VariantParser::StreamString css;
@@ -1754,6 +1754,38 @@ TEST_CASE("[Variant] array initializer list") {
CHECK(packed_arr[2] == 0);
}
TEST_CASE("[Variant] Writer and parser Vector2") {
Variant vec2_parsed;
String vec2_str;
String errs;
int line;
// Variant::VECTOR2 and Vector2 can be either 32-bit or 64-bit depending on the precision level of real_t.
{
Vector2 vec2 = Vector2(1.2, 3.4);
VariantWriter::write_to_string(vec2, vec2_str);
// Reminder: "1.2" and "3.4" are not exactly those decimal numbers. They are the closest float to them.
CHECK_MESSAGE(vec2_str == "Vector2(1.2, 3.4)", "Should write with enough digits to ensure parsing back is exact.");
VariantParser::StreamString stream;
stream.s = vec2_str;
VariantParser::parse(&stream, vec2_parsed, errs, line);
CHECK_MESSAGE(Vector2(vec2_parsed) == vec2, "Should parse back to the same Vector2.");
}
// Check with big numbers and small numbers.
{
Vector2 vec2 = Vector2(1.234567898765432123456789e30, 1.234567898765432123456789e-10);
VariantWriter::write_to_string(vec2, vec2_str);
#ifdef REAL_T_IS_DOUBLE
CHECK_MESSAGE(vec2_str == "Vector2(1.2345678987654322e+30, 1.2345678987654322e-10)", "Should write with enough digits to ensure parsing back is exact.");
#else
CHECK_MESSAGE(vec2_str == "Vector2(1.2345679e+30, 1.2345679e-10)", "Should write with enough digits to ensure parsing back is exact.");
#endif
VariantParser::StreamString stream;
stream.s = vec2_str;
VariantParser::parse(&stream, vec2_parsed, errs, line);
CHECK_MESSAGE(Vector2(vec2_parsed) == vec2, "Should parse back to the same Vector2.");
}
}
TEST_CASE("[Variant] Writer and parser array") {
Array a = build_array(1, String("hello"), build_array(Variant()));
String a_str;