Calculation Error in DQL

Dgraph version: Standalone:latest
Steps to reproduce:
Schema:

<dgraph.cors>: [string] @index(exact) @upsert .
<dgraph.graphql.schema>: string .
<dgraph.graphql.schema_created_at>: datetime .
<dgraph.graphql.schema_history>: string .
<dgraph.graphql.xid>: string @index(exact) @upsert .
<experimentName>: string @index(exact) .
<name>: string @index(exact) .
<option1>: [uid] .
<option2>: [uid] .
<result>: [uid] @count @reverse .
type <dgraph.graphql> {
	dgraph.graphql.schema
	dgraph.graphql.xid
}
type <dgraph.graphql.history> {
	dgraph.graphql.schema_history
	dgraph.graphql.schema_created_at
}

Mutation:

{
  set{
    _:exp <name> "experiment" .
    _:exp <option1> _:heads .
    _:exp <option2> _:tails .
    
    _:heads <name> "heads" .    
    _:tails <name> "tails" .
    _:exp1 <result> _:heads .
    _:exp2 <result> _:heads .
    _:exp3 <result> _:heads .
    _:exp4 <result> _:heads .

    _:expt1 <result> _:tails .
    _:expt2 <result> _:tails .
    _:expt3 <result> _:tails .
    _:expt4 <result> _:tails .
  }
}

Query:

{
  q(func: eq(name, "experiment")) {    
    option1{
      h as count(~result)
    }
    h1 as max(val(h))
    option2{      
      t as count(~result)      
    }
    t1 as max(val(t))
    total as math( h1 + t1)
    prob_heads: math( (h1*100) / total  )
    
    result1 :  math ( 4*100 / 8  )
    result2 :  math ( (4*100) / 8  )
  }
}

Result:

{
  "data": {
    "q": [
      {
        "option1": [
          {
            "count(~result)": 4
          }
        ],
        "max(val(h))": 4,
        "option2": [
          {
            "count(~result)": 4
          }
        ],
        "max(val(t))": 4,
        "val(total)": 8,
        "prob_heads": 50,
        "result1": 48,
        "result2": 50
      }
    ]
  }
}

Bug: Please note the difference between result1 and result2 (the rest can be effectively ignored, using variables instead of hard-coded numbers also results in the same bug). It should be the same, as it looks to be the same expression essentially.

1 Like

I won’t call this a bug. It really depends on how the expression is interpreted and in which order.
In this case, following the BODMAS rule, the division takes place before multiplication. And due to integer division (100/8) being equal to 12 we get the above difference.

There is no universal convention on whether to use the BODMAS or the PEMDAS rule and using any of the two is going to result in different answers for ambiguous expressions like 4*100/8 .

References:
https://math.berkeley.edu/~gbergman/misc/numbers/ord_ops.html

That is interesting to note. I will try to remember that when using math it evalutates every step in int and not float.

How does this work if any of the inputs is a float? math( 4 * 99.99 / 8 ) Does it still do every operation in int and converts 99.99 to 100 ?

No. In case one of the arguments in the expression is float, it will use the float. In this case the answer for both result1 and result2 will be 49.95 .

It evaluates every step in int only when all argumets are in int . If you provide any of the arguments in float, it will use float for every step. For example, (4 * 100.0 / 8) evaluates to 50. It uses float for evaluation because 100 is specified as 100.0 .

1 Like