Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precision problem of cJSON_AddNumberToObject(); with double and float. #117

Closed
ironengineer opened this issue Feb 23, 2017 · 7 comments
Closed

Comments

@ironengineer
Copy link

Question:
How can I add the double value only with given precision as provided 100.2 instead of 100.200000. Is it possible to generate the expected result below?
(Also when I gave the same number as float number = 100.2`; generated json: {"number value":100.199997})

Example code:

double number = 100.2;
cJSON_AddNumberToObject(json, "number value", number);

Expected result:
{"number value":100.2}

Generated result:
{"number value":100.200000}

@FSMaxB
Copy link
Collaborator

FSMaxB commented Feb 23, 2017

I am aware of this problem and it is one of the problem areas of cJSON. There are two conflicting goals.

  1. Numbers should not loose information when printing them to json and then reading them back.
  2. Printed numbers should look nice to humans.

Currently cJSON doesn't do a good job at both of them.

Printing numbers in a way that they look good for humans is hard, you have to come up with heuristics on what to do in several cases and I haven't found a good solution yet. (Ideally there would be some code that somebody else wrote, so I can get inspired).

One thing I could probably do is to trim trailing zeroes.

@mapleez
Copy link

mapleez commented Mar 1, 2017

Consider using a byte array buffer instead of explicit data type in cJSON structure to store data could be a good approach. That is to say we only use the buffer and flag it's type information.

@FSMaxB
Copy link
Collaborator

FSMaxB commented Mar 1, 2017

@mapleez I'm not sure what you are proposing.

If I understand you correctly, you want me to store numbers as a string in the cJSON struct.

I don't want to do this in the parser, because it will take much more memory, but if you create the cJSON struct yourself, you can make a struct with the type cJSON_Raw that contains the number you want to print as a string.

@mapleez
Copy link

mapleez commented Mar 1, 2017

Hmm... Could i understand a cJSON struct entity as a JSON object or an JSON array? Was i correct? If so ...
I propose to replace some cJSON fields (like 'valueint', 'valuedouble') with a char* ptr to store value. If the value type is, for example, int (it's sizeof <= intptr_t), we could store it directly into the char* ptr variable. And if it's a string(char*), we alloc and copy. Use the type field to identify value's type. Another approach is we could use an union with explicit type. e.g.

cJSON {
  union {
      int v_int;
      double v_double;
      float v_float;
      char* v_whatever;
  }
}

@FSMaxB
Copy link
Collaborator

FSMaxB commented Mar 1, 2017

@mapleez See #63

@FSMaxB
Copy link
Collaborator

FSMaxB commented Mar 5, 2017

@ironengineer The problem with many zero digits at the end has been fixed in release 1.4.0.

Fixing the precision in general is still a problem that has to be addressed.

Closing this issue for now.

@FSMaxB FSMaxB closed this as completed Mar 5, 2017
@FSMaxB
Copy link
Collaborator

FSMaxB commented May 2, 2017

Since version 1.5.0 cJSON doesn't loose any precision when printing anymore at least.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants