1

There is a json which contain numbers with long fractional part:

json = <<-JSON
{
  "number": 12.12345678910111213141516
}
JSON

But when making JSON.parse numbers become truncated:

require 'json'
JSON.parse(json)
#=> {"number"=>12.123456789101112}

But for me it's pretty critical to have the whole number.

Is there any way to save fractional part and prevent it from truncating when parsing json?

Stefan
  • 109,145
  • 14
  • 143
  • 218
pandomic
  • 607
  • 1
  • 6
  • 17
  • Is there any chance to _tune_ the json _publisher_ to provide these numbers as strings? – Aleksei Matiushkin Dec 19 '17 at 10:56
  • How does that JSON get created? – Stefan Pochmann Dec 19 '17 at 11:26
  • And can you show a real such number, not just that artificial example? – Stefan Pochmann Dec 19 '17 at 11:30
  • @mudasobwa the consumer seems to need some tuning. – Stefan Dec 19 '17 at 12:46
  • @StefanPochmann the number in the OP's example looks fine to me – it is being truncated. – Stefan Dec 19 '17 at 12:48
  • @Stefan The fractional part is the concatenation of the numbers 1 to 16. Do you think that's really a real number they got, not just one they made up for an MCVE? – Stefan Pochmann Dec 19 '17 at 12:50
  • 1
    @StefanPochmann apparently, it is just an example value, but it doesn't alter the problem. – Stefan Dec 19 '17 at 12:56
  • @Stefan It might. What if the JSON string contains `0.1000000000000000055511151231257827021181583404541015625` and they're complaining about ending up with `0.1`? They'd be wrong to complain, since they'd then have the exact number. – Stefan Pochmann Dec 19 '17 at 12:58
  • @StefanPochmann according to the question's title the OP wants a BigDecimal, not a Float. – Stefan Dec 19 '17 at 13:17
  • @Stefan Yes, but maybe they just *want* that based on a misunderstanding and don't actually *need* that. – Stefan Pochmann Dec 19 '17 at 13:18
  • @StefanPochmann I would be very surprised to see JSON data with exact (double-precision) floating point values, but you never know ;-) – Stefan Dec 19 '17 at 13:21
  • @Stefan Well I'm also surprised to see JSON data allegedly needing BigDecimal :-) – Stefan Pochmann Dec 19 '17 at 13:25
  • @StefanPochmann how is `0.1` the exact number in any way? the **exact** number is the number you're saying their wrong to complain about not getting. `0.1` is NOT `0.1000000000000000055511151231257827021181583404541015625`; that's a pure, undeniable fact. the **exact** precision might not be **necessary**, but that isn't really for you to decide for them in a perfectly valid question – Sampson Crowley Jul 02 '20 at 01:11
  • @SampsonCrowley The values of `0.1` and `0.1000000000000000055511151231257827021181583404541015625` are exactly the same (namely 0.1000000000000000055511151231257827021181583404541015625). – Stefan Pochmann Jul 02 '20 at 12:07
  • @StefanPochmann no... they are NOT *exactly* the same, one of them is *exactly* `0.1`, and the other is larger than `0.1` by `0.0000000000000000055511151231257827021181583404541015625`. I really don't understand how you possibly think those are the same number. Again, the **precision** might not actually **matter** depending on the use-case, but that has nothing to do with the question – Sampson Crowley Jul 02 '20 at 17:59
  • @SampsonCrowley They do have the exact same value. `0.1` is **not** 0.1 but 0.1000000000000000055511151231257827021181583404541015625. I suggest you learn how floating point works, maybe start [here](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). – Stefan Pochmann Jul 02 '20 at 22:06
  • @StefanPochmann you realize that's exactly the issue here right? that floating point numbers are **not** *accurate*. I didn't say *anything* about hardware representation inaccuracies, did I? I said `0.1` is *not* `0.1000000000000000055511151231257827021181583404541015625`. **Because it is not**. Literally this entire question is about *not* using *inaccurate* floating point numbers – Sampson Crowley Jul 03 '20 at 01:45
  • @StefanPochmann at no point did you make the statement *decimal* `0.1` is *binary64* `0.1000000000000000055511151231257827021181583404541015625` those are comparing two completely different number *representations*, not two numbers – Sampson Crowley Jul 03 '20 at 01:50
  • @SampsonCrowley Oh good, you're aware of the difference between numbers and number representations. Now you just need to realize that `0.1` and `0.1000000000000000055511151231257827021181583404541015625` are the same number (represented by the different representations "`0.1`" and "`0.1000000000000000055511151231257827021181583404541015625`"). – Stefan Pochmann Jul 03 '20 at 10:40
  • And in case it's not clear (although the guy I originally talked with understood me perfectly), I don't mark something as code just for fun (as it seems you do). I mark something as code so you read it as code. "0.1" and "`0.1`" are two different representations, the former of the number 0.1 and the latter of the number 0.1000000000000000055511151231257827021181583404541015625. – Stefan Pochmann Jul 03 '20 at 10:40

1 Answers1

2

One might use any more sophisticated parser, like Oj:

main ▶ Oj.load '{"number": 12.12345678910111213141516123456789123456789}'
#⇒{
#  "number" => 12.12345678910111213141516123456789123456789
# }
main ▶ Oj.load('{"number": 12.12345678910111213141516}')["number"].class
#⇒ BigDecimal < Numeric
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160