From a6d3f3a59aedb401c89b530b108f4df24e1e4cb5 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Tue, 7 Nov 2017 23:25:27 -0500 Subject: [PATCH] Restore round-to-even behavior. --- src/unity.c | 19 +++++++++--- test/tests/testunity.c | 70 +++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/unity.c b/src/unity.c index 03d3fbf..fc3ae53 100644 --- a/src/unity.c +++ b/src/unity.c @@ -292,7 +292,7 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) else if (isinf(number)) UnityPrint("inf"); else { - UNITY_INT32 n = 0; + UNITY_INT32 n_int = 0, n; int exponent = 0; int decimals, digits; char buf[16]; @@ -330,16 +330,25 @@ void UnityPrintFloat(const UNITY_DOUBLE input_number) * freeing up significant bits in the fractional part. */ UNITY_DOUBLE factor = 1.0f; - n = (UNITY_INT32)number; - number -= (UNITY_DOUBLE)n; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; - while (n < min_scaled) { n *= 10; factor *= 10.0f; exponent--; } + 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; + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#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 = min_scaled; diff --git a/test/tests/testunity.c b/test/tests/testunity.c index 0aa6914..2d6a5ab 100644 --- a/test/tests/testunity.c +++ b/test/tests/testunity.c @@ -4468,7 +4468,6 @@ void testFloatPrinting(void) #else TEST_ASSERT_EQUAL_PRINT_FLOATING("0", 0.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("4.99e-07", 0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("5.000001e-07", 0.00000050000005f); TEST_ASSERT_EQUAL_PRINT_FLOATING("0.1004695", 0.100469499f); TEST_ASSERT_EQUAL_PRINT_FLOATING("2", 1.9999995f); /*Rounding to int place*/ TEST_ASSERT_EQUAL_PRINT_FLOATING("1", 1.0f); @@ -4481,7 +4480,6 @@ void testFloatPrinting(void) TEST_ASSERT_EQUAL_PRINT_FLOATING("-0", -0.0f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-4.99e-07", -0.000000499f); - TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.000001e-07", -0.00000050000005f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-0.1004695", -0.100469499f); TEST_ASSERT_EQUAL_PRINT_FLOATING("-2", -1.9999995f); /*Rounding to int place*/ TEST_ASSERT_EQUAL_PRINT_FLOATING("-1", -1.0f); @@ -4512,6 +4510,25 @@ void testFloatPrinting(void) #endif } +void testFloatPrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_INCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + #ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0004882813", 0.00048828125f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("488281.3", 488281.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5.000001e-07", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5.000001e-07", -0.00000050000005f); + #else /* Default to Round ties to even */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("0.0004882812", 0.00048828125f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("488281.2", 488281.25f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("5e-07", 0.00000050000005f); + TEST_ASSERT_EQUAL_PRINT_FLOATING("-5e-07", -0.00000050000005f); + #endif +#endif +} + void testFloatPrintingInfinityAndNaN(void) { #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || !defined(USING_OUTPUT_SPY) @@ -4529,31 +4546,15 @@ void testFloatPrintingInfinityAndNaN(void) static void printFloatValue(float f) { char expected[18]; - char expected_lower[18]; - char expected_higher[18]; startPutcharSpy(); - UnityPrintFloat(f); sprintf(expected, "%.9g", f); - /* We print all NaN's as "nan", not "-nan" */ - if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); - - strcpy(expected_lower, expected); - strcpy(expected_higher, expected); - - /* Allow for rounding differences in the last digit */ - double lower = (double)f * 0.9999999995; - double higher = (double)f * 1.0000000005; - - if(isfinite(lower)) sprintf(expected_lower, "%.9g", lower); - if(isfinite(higher)) sprintf(expected_higher, "%.9g", higher); + if (strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); - if (strcmp(expected, getBufferPutcharSpy()) != 0 && - strcmp(expected_lower, getBufferPutcharSpy()) != 0 && - strcmp(expected_higher, getBufferPutcharSpy()) != 0) + if (strcmp(expected, getBufferPutcharSpy())) { /* Fail with diagnostic printing */ TEST_ASSERT_EQUAL_PRINT_FLOATING(expected, f); @@ -4571,13 +4572,11 @@ static void printFloatValue(float f) char expected_higher3[18]; startPutcharSpy(); - UnityPrintFloat(f); sprintf(expected, "%.7g", f); - /* We print all NaN's as "nan", not "-nan" */ - if(strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); + if (strcmp(expected, "-nan") == 0) strcpy(expected, "nan"); strcpy(expected_lower, expected); strcpy(expected_lower2, expected); @@ -4594,17 +4593,17 @@ static void printFloatValue(float f) if(isfinite(higher)) sprintf(expected_higher, "%.7g", higher); /* Outside [1,10000000] allow for relative error of +/-2.5e-7 */ - if(f < 1.0 || f > 10000000) + if (f < 1.0 || f > 10000000) { double lower2 = (double)f * 0.99999985; double lower3 = (double)f * 0.99999975; double higher2 = (double)f * 1.00000015; double higher3 = (double)f * 1.00000025; - if(isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); - if(isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); - if(isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); - if(isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); + if (isfinite(lower2)) sprintf(expected_lower2, "%.7g", lower2); + if (isfinite(lower3)) sprintf(expected_lower3, "%.7g", lower3); + if (isfinite(higher2)) sprintf(expected_higher2, "%.7g", higher2); + if (isfinite(higher3)) sprintf(expected_higher3, "%.7g", higher3); } if (strcmp(expected, getBufferPutcharSpy()) != 0 && @@ -5362,6 +5361,21 @@ void testDoublePrinting(void) #endif } +void testDoublePrintingRoundTiesToEven(void) +{ +#if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) + TEST_IGNORE(); +#else + #ifdef UNITY_ROUND_TIES_AWAY_FROM_ZERO + TEST_ASSERT_EQUAL_PRINT_FLOATING("1.00000001e+10", 10000000050.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719925e+15", 9007199245000000.0); + #else /* Default to Round ties to even */ + TEST_ASSERT_EQUAL_PRINT_FLOATING("1e+10", 10000000050.0); + TEST_ASSERT_EQUAL_PRINT_FLOATING("9.00719924e+15", 9007199245000000.0); + #endif +#endif +} + void testDoublePrintingInfinityAndNaN(void) { #if defined(UNITY_EXCLUDE_FLOAT_PRINT) || defined(UNITY_EXCLUDE_DOUBLE) || !defined(USING_OUTPUT_SPY) -- GitLab