ChaiScript/unittests/float_literal_test.cpp
leftibot 6517bb38a7 Fix #378: Replace hand-rolled number parsing with std::from_chars
The custom parse_num floating-point implementation produced slightly
different results from the C++ compiler's own literal parsing (e.g.
1.1e-4 was off by a few ULPs). Replace it with std::from_chars which
is locale-independent and matches compiler precision exactly. Also
migrate integer parsing in buildInt from std::stoll/stoull to
std::from_chars, fix the JSON number parser to pass the full numeric
string to from_chars instead of splitting mantissa/exponent and using
std::pow, and update parse_string to use from_chars for arithmetic types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 18:25:47 -06:00

53 lines
1.7 KiB
C++

#include "../static_libs/chaiscript_parser.hpp"
#include "../static_libs/chaiscript_stdlib.hpp"
#include <chaiscript/chaiscript_basic.hpp>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <string>
#define TEST_FLOAT_LITERAL(v) test_float_literal(v, #v)
template<typename T>
bool test_float_literal(const T val, const std::string &str) {
chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser());
const T val2 = chai.eval<T>(str);
const bool pass = (val == val2);
std::cout << (pass ? "PASS" : "FAIL") << " (" << str << ") C++="
<< std::setprecision(20) << val << " chai=" << val2 << "\n";
return pass;
}
int main() {
bool success = true;
// Issue #378: scientific notation parsing inaccuracies
success = TEST_FLOAT_LITERAL(1.1e-4) && success;
success = TEST_FLOAT_LITERAL(1.5e+3) && success;
success = TEST_FLOAT_LITERAL(3.14159) && success;
success = TEST_FLOAT_LITERAL(2.718281828459045) && success;
success = TEST_FLOAT_LITERAL(1.0e10) && success;
success = TEST_FLOAT_LITERAL(1.0e-10) && success;
success = TEST_FLOAT_LITERAL(0.1) && success;
success = TEST_FLOAT_LITERAL(0.2) && success;
success = TEST_FLOAT_LITERAL(1.7976931348623157e+308) && success;
success = TEST_FLOAT_LITERAL(2.2250738585072014e-308) && success;
// Float suffix
success = TEST_FLOAT_LITERAL(1.1e-4f) && success;
success = TEST_FLOAT_LITERAL(3.14f) && success;
// Long double suffix
success = TEST_FLOAT_LITERAL(1.1e-4l) && success;
success = TEST_FLOAT_LITERAL(3.14l) && success;
if (success) {
std::cout << "All float literal tests passed.\n";
return 0;
} else {
std::cout << "FLOAT LITERAL TEST FAILURE\n";
return 1;
}
}