Skip to content

Commit bbe442f

Browse files
committed
Regards #109: Now correctly rounding down the computed base-10 exponent. CAVEAT: This exposes an issue with printing values having exponent -308 (the minimum exponent for double's); and - we see some divergence from perfect corrtness with higher precision values.
1 parent df0fb9e commit bbe442f

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

src/printf/printf.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,15 @@ static void print_decimal_number(output_gadget_t* output, double number, printf_
765765
print_broken_up_decimal(value_, output, precision, width, flags, buf, len);
766766
}
767767

768+
// A floor function - but one which only works for numbers whose
769+
// floor value is representable by an int.
770+
static int bastardized_floor(double x)
771+
{
772+
if (x >= 0) { return (int) x; }
773+
int n = (int) x;
774+
return ( ((double) n) == x ) ? n : n-1;
775+
}
776+
768777
#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
769778
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <[email protected]>
770779
static void print_exponential_number(output_gadget_t* output, double number, printf_size_t precision, printf_size_t width, printf_flags_t flags, char* buf, printf_size_t len)
@@ -791,9 +800,11 @@ static void print_exponential_number(output_gadget_t* output, double number, pri
791800
// drop the exponent, so conv.F comes into the range [1,2)
792801
conv.U = (conv.U & (( (double_uint_t)(1) << DOUBLE_STORED_MANTISSA_BITS) - 1U)) | ((double_uint_t) DOUBLE_BASE_EXPONENT << DOUBLE_STORED_MANTISSA_BITS);
793802
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
794-
exp10 = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
803+
double exp10_ = (0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
804+
805+
exp10 = bastardized_floor(exp10_);
795806
// now we want to compute 10^exp10 but we want to be sure it won't overflow
796-
exp2 = (int)(exp10 * 3.321928094887362 + 0.5);
807+
exp2 = bastardized_floor(exp10 * 3.321928094887362 + 0.5);
797808
const double z = exp10 * 2.302585092994046 - exp2 * 0.6931471805599453;
798809
const double z2 = z * z;
799810
conv.U = ((double_uint_t)(exp2) + DOUBLE_BASE_EXPONENT) << DOUBLE_STORED_MANTISSA_BITS;

test/test_suite.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,30 @@ TEST_CASE("floating-point specifiers with 31-32 bit integer values", "[]" ) {
873873
}
874874
#endif
875875

876+
#if PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS
877+
TEST_CASE("tiny floating-point values", "[]" ) {
878+
char buffer[100];
879+
// boltzman_s_constant = 1.380651569e-23;
880+
881+
PRINTING_CHECK("1e-23", ==, sprintf_, buffer, "%.0e", 1.380651569e-23);
882+
PRINTING_CHECK("1.4e-23", ==, sprintf_, buffer, "%.1e", 1.380651569e-23);
883+
PRINTING_CHECK("1.38e-23", ==, sprintf_, buffer, "%.2e", 1.380651569e-23);
884+
PRINTING_CHECK("1.381e-23", ==, sprintf_, buffer, "%.3e", 1.380651569e-23);
885+
PRINTING_CHECK("1.3807e-23", ==, sprintf_, buffer, "%.4e", 1.380651569e-23);
886+
PRINTING_CHECK("1.38065e-23", ==, sprintf_, buffer, "%.5e", 1.380651569e-23);
887+
PRINTING_CHECK("1.380652e-23", ==, sprintf_, buffer, "%.6e", 1.380651569e-23);
888+
PRINTING_CHECK("1.3806516e-23", ==, sprintf_, buffer, "%.7e", 1.380651569e-23);
889+
PRINTING_CHECK("1.38065157e-23", ==, sprintf_, buffer, "%.8e", 1.380651569e-23);
890+
PRINTING_CHECK("1.380651569e-23", ==, sprintf_, buffer, "%.9e", 1.380651569e-23);
891+
PRINTING_CHECK("1.3806515690e-23", ==, sprintf_, buffer, "%.10e", 1.380651569e-23);
892+
PRINTING_CHECK("1.38065156900e-23", ==, sprintf_, buffer, "%.11e", 1.380651569e-23);
893+
PRINTING_CHECK("1.380651569000e-23", ==, sprintf_, buffer, "%.12e", 1.380651569e-23);
894+
PRINTING_CHECK("1.3806515690000e-23", ==, sprintf_, buffer, "%.13e", 1.380651569e-23);
895+
PRINTING_CHECK("1.38065156900000e-23", ==, sprintf_, buffer, "%.14e", 1.380651569e-23);
896+
PRINTING_CHECK("1.380651569000000e-23", ==, sprintf_, buffer, "%.15e", 1.380651569e-23);
897+
PRINTING_CHECK("1.3806515690000000e-23", ==, sprintf_, buffer, "%.16e", 1.380651569e-23);
898+
}
899+
#endif
876900

877901
#if PRINTF_SUPPORT_DECIMAL_SPECIFIERS
878902
TEST_CASE("fallback from decimal to exponential", "[]" ) {

0 commit comments

Comments
 (0)