mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2025-12-18 06:18:37 +08:00
Merge pull request #299 from jlindgren90/float-printing
Allow UnityPrintFloat() to print a 7th digit.
This commit is contained in:
84
src/unity.c
84
src/unity.c
@@ -262,13 +262,25 @@ void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number)
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
#ifndef UNITY_EXCLUDE_FLOAT_PRINT
|
||||
/* This function prints a floating-point value in a format similar to
|
||||
* printf("%.6g"). It can work with either single- or double-precision,
|
||||
* but for simplicity, it prints only 6 significant digits in either case.
|
||||
* Printing more than 6 digits accurately is hard (at least in the single-
|
||||
* precision case) and isn't attempted here. */
|
||||
/*
|
||||
* This function prints a floating-point value in a format similar to
|
||||
* printf("%.7g") on a single-precision machine or printf("%.9g") on a
|
||||
* double-precision machine. The 7th digit won't always be totally correct
|
||||
* in single-precision operation (for that level of accuracy, a more
|
||||
* complicated algorithm would be needed).
|
||||
*/
|
||||
void UnityPrintFloat(const UNITY_DOUBLE input_number)
|
||||
{
|
||||
#ifdef UNITY_INCLUDE_DOUBLE
|
||||
static const int sig_digits = 9;
|
||||
static const UNITY_INT32 min_scaled = 100000000;
|
||||
static const UNITY_INT32 max_scaled = 1000000000;
|
||||
#else
|
||||
static const int sig_digits = 7;
|
||||
static const UNITY_INT32 min_scaled = 1000000;
|
||||
static const UNITY_INT32 max_scaled = 10000000;
|
||||
#endif
|
||||
|
||||
UNITY_DOUBLE number = input_number;
|
||||
|
||||
/* print minus sign (including for negative zero) */
|
||||
@@ -293,27 +305,71 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number)
|
||||
}
|
||||
else
|
||||
{
|
||||
UNITY_INT32 n_int = 0, n;
|
||||
int exponent = 0;
|
||||
int decimals, digits;
|
||||
UNITY_INT32 n;
|
||||
char buf[16] = {0};
|
||||
|
||||
/* scale up or down by powers of 10 */
|
||||
while (number < 100000.0f / 1e6f) { number *= 1e6f; exponent -= 6; }
|
||||
while (number < 100000.0f) { number *= 10.0f; exponent--; }
|
||||
while (number > 1000000.0f * 1e6f) { number /= 1e6f; exponent += 6; }
|
||||
while (number > 1000000.0f) { number /= 10.0f; exponent++; }
|
||||
/*
|
||||
* Scale up or down by powers of 10. To minimize rounding error,
|
||||
* start with a factor/divisor of 10^10, which is the largest
|
||||
* power of 10 that can be represented exactly. Finally, compute
|
||||
* (exactly) the remaining power of 10 and perform one more
|
||||
* multiplication or division.
|
||||
*/
|
||||
if (number < 1.0f)
|
||||
{
|
||||
UNITY_DOUBLE factor = 1.0f;
|
||||
|
||||
while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; }
|
||||
while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; }
|
||||
|
||||
number *= factor;
|
||||
}
|
||||
else if (number > (UNITY_DOUBLE)max_scaled)
|
||||
{
|
||||
UNITY_DOUBLE divisor = 1.0f;
|
||||
|
||||
while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; }
|
||||
while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; }
|
||||
|
||||
number /= divisor;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* In this range, we can split off the integer part before
|
||||
* doing any multiplications. This reduces rounding error by
|
||||
* freeing up significant bits in the fractional part.
|
||||
*/
|
||||
UNITY_DOUBLE factor = 1.0f;
|
||||
n_int = (UNITY_INT32)number;
|
||||
number -= (UNITY_DOUBLE)n_int;
|
||||
|
||||
while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; }
|
||||
|
||||
number *= factor;
|
||||
}
|
||||
|
||||
/* round to nearest integer */
|
||||
n = ((UNITY_INT32)(number + number) + 1) / 2;
|
||||
if (n > 999999)
|
||||
|
||||
#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO
|
||||
/* round to even if exactly between two integers */
|
||||
if ((n & 1) && ((UNITY_DOUBLE)n - number == 0.5f))
|
||||
n--;
|
||||
#endif
|
||||
|
||||
n += n_int;
|
||||
|
||||
if (n >= max_scaled)
|
||||
{
|
||||
n = 100000;
|
||||
n = min_scaled;
|
||||
exponent++;
|
||||
}
|
||||
|
||||
/* determine where to place decimal point */
|
||||
decimals = (exponent <= 0 && exponent >= -9) ? -exponent : 5;
|
||||
decimals = (exponent <= 0 && exponent >= -(sig_digits + 3)) ? -exponent : (sig_digits - 1);
|
||||
exponent += decimals;
|
||||
|
||||
/* truncate trailing zeroes after decimal point */
|
||||
|
||||
Reference in New Issue
Block a user