Some problems about float types

mutate:

{
  set{
    _:42608 <test> "37.79697544"^^<xs:float>   .   #
  }
}

query:

{
  
  query(func: has(test))@filter(eq(test,37.79697544)){
    test
  }
}

respones:

  "data": {
    "query": [
      {
        "test": 37.796975
      }
    ]
  },

37.796975 != 37.79697544

if you use 37.796975 to query,

{
  
  query(func: has(test))@filter(eq(test,37.796975)){
    test
  }
}

it returns Your query did not return any results

I think if we remove rounding in the JSON serialization the rest will work as expected.

Equality tests with float numbers are broken “by design”.

We probably should file a bug about this. What do you think @MichelDiz?

2 Likes

Not sure.

He is using “eq”, equal to. By design seems logic to not return anything. For the query is not exactly the same as the one recorded. I would recommend using inequality combined with less than and greater than or equal.

{
  query(func: has(test))@filter(ge(test,37.796975) OR le(test,37.79697544)){
    test
  }
}

As it comes to float I do not know what the implication would be. Your call @paulftw . Let’s take the fractions of Bitcoin for example.

37.79697544 BTC = 242,165.22 USD
37.796975 BTC = 242,165,36 USD

0.14 cents difference. So every fraction of the float matters. In the sense that, they are not equal.

https://docs.dgraph.io/query-language#inequality

https://docs.dgraph.io/query-language#less-than-less-than-or-equal-to-greater-than-and-greater-than-or-equal-to

Cheers.

PS. Yeah, @paulftw I noticed right now that the correct thing was to return the recorded number completely. And that does not happen. It’s a bug or okay? (*) limitation?.

*I do not think it’s ok, it can be problematic for developers working with fractions.

{
  query(func: has(test))@filter(ge(test,37.796975) OR le(test,37.796975)){
    test
  }
{
  
  query2(func: has(test))@filter(eq(test,37.796975)){
    test
  }
}
    {
  
  query3(func: has(test))@filter(eq(test,37.79697544)){
    test
  }
}
}
{
  "data": {
    "query": [
      {
        "test": 37.796975 #should return the whole number 37.79697544
      }
    ],
    "query2": [],
    "query3": [
      {
        "test": 37.796975 #should return the whole number mainly here.
      }
    ]
  }

Adding one more references:

Dgraph records this like this

<_:uid2711> <test> "3.779697544E+01"^^<xs:float> .

Also supporting BigDecimal types could be related to this.

https://github.com/dgraph-io/dgraph/issues/926

Also can be related Inferred schemas treat integers as floats, may silently alter data · Issue #2377 · dgraph-io/dgraph · GitHub

One invariant I think everyone expects is:

when one query returns { “foo”: } then a query with eq(foo, ) must alway pick the original node.

No mater if is a string, integer, or float. As long as it is JSON serializable to the same string.

BigDecimal and RDF are probably unrelated although important issues.

1 Like

Running into the same issue when storing Latitude/Longitude as a float. Chops off last digits, which would put you in a completely different location.

Hi there, so… any updates here? Now I’ve been working with float number and rounding is very annoying. I want to get the whole number, not only 6 digit after point :face_holding_back_tears:

1 Like

Hi Nikita,

Can you clarify your use case and the impact? Regrettably, the issue with computers using binary but humans decimal causes some rounding at some level of precision pretty much no matter what.

So if you are storing a value using a decimal representation, and it is stored slightly differently due to finite precision and binary conversion, but trying to do an exact match, I do not know if that will ever work, regardless of adding a couple digits more precision.

Let us know your use case and we can consider approaches, though.

Hi Damon,

I want to store in dgraph floats like 0.0000001234 and I expect to get it from dgraph as 0.0000001234 (or 1.234000e-07) and not like 0.0.

And now I have to store 2 predicates with string and float types, because dgraph doesn’t allow to return floats in at least scientific notation :c.

I know issues with storing float values, but my topic meant “how dgraph returns float value to users”.