Use dragonbox to print floats (#481)

* add new float printer

* more includes

* compare as floats
This commit is contained in:
water111
2021-05-13 21:05:05 -04:00
committed by GitHub
parent 790e65a78c
commit 60c670df3a
6 changed files with 3486 additions and 42 deletions
+5 -42
View File
@@ -42,6 +42,7 @@
#include "Object.h"
#include "common/util/FileUtil.h"
#include "third-party/fmt/core.h"
#include "common/util/print_float.h"
namespace goos {
@@ -83,51 +84,13 @@ std::string object_type_to_string(ObjectType type) {
}
/*!
* Special case to print a float with the %g format specifier
* Special case to print a float
*/
template <>
std::string fixed_to_string(FloatType x) {
char buff[256];
s64 rounded = x;
bool exact_int = ((float)rounded) == x;
// it's an integer number, so let's just get this over with asap
if (exact_int) {
sprintf(buff, "%" PRId64 ".0", rounded);
return {buff};
} else {
// not an integer - see how many decimal cases we need
// i'm not sure what happens if x is a NaN/inf...
// buffer for format string
char fmt_buf[256];
// we are going to try our hardest to make sure the output is re-parseable
// for what it's worth, the lowest representable 32-bit floating point number has almost 50
// decimal cases, although:
// - by that point we should just be using scientific notation instead?
// - the PS2 DOES NOT DENORMALIZE FLOATS, or handle NaNs/infs! so the representation wouldn't
// be accurate anyway
// - we might not ever encounter numbers like that. the pretty printer has a "banned" floats
// list just in case
// 99 might seem high, but we are gonna get the result in under 10 or so most of the time, so
// it's fine.
// maybe there's some math principles or other tricks to optimize this?
for (int i = 1; i <= 99; ++i) {
// generate the format string
sprintf(fmt_buf, "%%.%df", i);
sprintf(buff, fmt_buf, x);
auto float_from_string = float(std::stod(buff));
float value_as_float = float(x);
bool are_they_equal = float_from_string == value_as_float;
if (are_they_equal)
return {buff};
}
throw std::runtime_error("a float could not be represented accurately");
}
auto result = float_to_string(x);
assert((float)x == (float)std::stod(result));
return result;
}
/*!