3
$\begingroup$

I'm trying to merge list member with the same numerical key values:

a = {53.8 -> x, Floor[53.81`, 0.2] -> y};
Merge[a, Total]

then I get:

<|53.8 -> x, 53.8 -> y|>

So I check the output of Floor:

Floor[53.81`, 0.2] // FullForm
53.800000000000004`

I paste it into the expression to test their equality:

a = {53.8 -> x, 53.800000000000004` -> y};
a[[1, 1]] == a[[2, 1]]
Merge[a, Total]
True
<|53.8 -> x, 53.8 -> y|>

but when I insert one more zero into 53.800000000000004`:

a = {53.8 -> x, 53.8000000000000004` -> y};
a[[1, 1]] == a[[2, 1]]
Merge[a, Total]
True
<|53.8 -> x + y|>
  1. Seeing the long digits of FullForm, am I using Floor in the correct way?
  2. Does Merge use different number precision than other evaluations?
$\endgroup$
1
  • 4
    $\begingroup$ I think you're going to run into all sorts of headaches trying to figure out a general approach to force equality between finite precision quantities. I suggest you force them to rationals. For example Floor[53.81, 1/5] gives 269/5. You can use this as a normalizing function and apply it to all keys before merging. $\endgroup$
    – lericr
    Commented Sep 12 at 12:32

1 Answer 1

8
$\begingroup$

Association in Mathematica are implemented as hash tables (more precisely, they are actually hash array mapped tries). This means that keys are usually represented through their hashes, and the equality is checked neither with Equal (==) nor with SameQ (===), but by comparing the hashes.

There exists a function called Internal`HashSameQ, which you can use to see whether the two expression have the same hash:

53.8 == Floor[53.81`, 0.2]
(* True *)

53.8 === Floor[53.81`, 0.2]
(* True *)

Internal`HashSameQ[53.8, Floor[53.81`, 0.2]] 
(* False *)

This is why we can construct an Association having both 53.8 and 53.800000000000004 as a key:

<|53.8 -> x, 53.800000000000004 -> y|>
(* <|53.8 -> x, 53.8 -> y|> *)

There also exists a setting called Internal`$HashTolerance, which affects the behaviour of Internal`HashSameQ. It is by default set to approximately 0.30. For your purpose, you could increase it to achieve the desired merging:

Block[{Internal`$HashTolerance = 1},
 Merge[a, Total]
 ]
(* <|53.8 -> x + y|> *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.