Merge pull request #454 from Alanscut/float-compare

comparing double value with DBL_EPSILON
This commit is contained in:
Alan Wang 2020-04-02 20:09:42 +08:00 committed by GitHub
commit 23e4fbc639
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 20 additions and 9 deletions

View File

@ -37,7 +37,7 @@ else
endif endif
PIC_FLAGS = -fPIC PIC_FLAGS = -fPIC
R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion -Wfloat-equal $(CFLAGS) R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS)
uname := $(shell sh -c 'uname -s 2>/dev/null || echo false') uname := $(shell sh -c 'uname -s 2>/dev/null || echo false')

14
cJSON.c
View File

@ -43,6 +43,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <ctype.h> #include <ctype.h>
#include <float.h>
#ifdef ENABLE_LOCALES #ifdef ENABLE_LOCALES
#include <locale.h> #include <locale.h>
@ -68,6 +69,14 @@
#endif #endif
#define false ((cJSON_bool)0) #define false ((cJSON_bool)0)
/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
#ifndef isinf
#define isinf(d) (isnan((d - d)) && !isnan(d))
#endif
#ifndef isnan
#define isnan(d) (d != d)
#endif
typedef struct { typedef struct {
const unsigned char *json; const unsigned char *json;
size_t position; size_t position;
@ -522,7 +531,8 @@ static void update_offset(printbuffer * const buffer)
/* securely comparison of floating-point variables */ /* securely comparison of floating-point variables */
static cJSON_bool compare_double(double a, double b) static cJSON_bool compare_double(double a, double b)
{ {
return (fabs(a - b) <= CJSON_DOUBLE_PRECISION); double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
return (fabs(a - b) <= maxVal * DBL_EPSILON);
} }
/* Render the number nicely from the given item into a string. */ /* Render the number nicely from the given item into a string. */
@ -542,7 +552,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out
} }
/* This checks for NaN and Infinity */ /* This checks for NaN and Infinity */
if ((d * 0) != 0) if (isnan(d) || isinf(d))
{ {
length = sprintf((char*)number_buffer, "null"); length = sprintf((char*)number_buffer, "null");
} }

View File

@ -137,11 +137,6 @@ typedef int cJSON_bool;
#define CJSON_NESTING_LIMIT 1000 #define CJSON_NESTING_LIMIT 1000
#endif #endif
/* Precision of double variables comparison */
#ifndef CJSON_DOUBLE_PRECISION
#define CJSON_DOUBLE_PRECISION .0000000000000001
#endif
/* returns the version of cJSON as a string */ /* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void); CJSON_PUBLIC(const char*) cJSON_Version(void);

View File

@ -40,6 +40,8 @@
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
#include <float.h>
#include <math.h>
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning (pop) #pragma warning (pop)
@ -109,7 +111,8 @@ static int compare_strings(const unsigned char *string1, const unsigned char *st
/* securely comparison of floating-point variables */ /* securely comparison of floating-point variables */
static cJSON_bool compare_double(double a, double b) static cJSON_bool compare_double(double a, double b)
{ {
return (fabs(a - b) <= CJSON_DOUBLE_PRECISION); double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
return (fabs(a - b) <= maxVal * DBL_EPSILON);
} }

View File

@ -64,6 +64,9 @@ static void cjson_compare_should_compare_numbers(void)
TEST_ASSERT_TRUE(compare_from_string("1", "1", false)); TEST_ASSERT_TRUE(compare_from_string("1", "1", false));
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", true)); TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", true));
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", false)); TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", false));
TEST_ASSERT_TRUE(compare_from_string("1E100", "10E99", false));
TEST_ASSERT_FALSE(compare_from_string("0.5E-100", "0.5E-101", false));
TEST_ASSERT_FALSE(compare_from_string("1", "2", true)); TEST_ASSERT_FALSE(compare_from_string("1", "2", true));
TEST_ASSERT_FALSE(compare_from_string("1", "2", false)); TEST_ASSERT_FALSE(compare_from_string("1", "2", false));