What is wrong with RuleCondition here?

Here is an observation, not really an answer:

Hold@1.`5 /. x_Real :> RuleCondition[N[x] + $MachineEpsilon, True]
(* -> Hold[1.0000] *)

But:

Block[{Internal`$SameQTolerance = -Infinity},

Hold@1.`5 /. x_Real :> RuleCondition[N[x] + $MachineEpsilon, True] ] (* -> Hold[1.] *)

It does not help your test case because 1.`5 is SameQ 1. But I think this makes it a question of SameQ's problem, rather than RuleCondition's.

For completeness: Internal`$EqualTolerance and Internal`$HashTolerance have no effect. The test is definitely SameQ.

Since Alexey mentions that things were better in version 5 with respect to a tangentially related bug/oddity, it may be worth noting as well that in versions of Mathematica up to and including 7, we have a different result:

Hold@1`5 /. x_Real :> RuleCondition[N@x, True]
(* -> Hold[1.] *)
Hold@1`5 /. x_Real :> RuleCondition[N@2`5, True]
(* -> Hold[2.] *)
Hold@2`5 /. x_Real :> RuleCondition[N@2`5, True]
(* -> Hold[2.] *)
Hold@1`5 /. x_Real :> RuleCondition[N@t, True]
(* -> Hold[t] *)

This looks absolutely as one would expect. The optimization of SameQ in version 8 is the clear culprit.

Unfortunately, we cannot work around the problem by replacing SameQ with a more stringent test:

Internal`HashSameQ[1., 1.`5]
(* -> False *)

Block[{SameQ = Internal`HashSameQ, Internal`$HashTolerance = -Infinity}, 
 Hold@1.`5 /. x_Real :> RuleCondition[N[x], True]
]
(* -> Hold[1.0000] *)

It seems that RuleCondition is hard-coded to call the SameQ code no matter how SameQ is defined at the top level. This might be considered a bug in RuleCondition in addition to the one in SameQ.

I am of the view that the SameQ behavior is a bug, because while I have always thought that the value of Internal`$SameQTolerance being anything other than -Infinity is a bad idea, for numbers with different Precision to compare as being the same is an explicit violation of Mathematica's numerical model of floating-point numbers being distributions. I think one cannot have a serious conceptual inconsistency like this and not call it a bug.


Update Jan 22nd: WRI Tech Support indicates that the fixes for all the test cases below, including the ones that don't depend on SameQ, may land in the next point release. The fixes could miss the point release if they cause other problems with higher severity.

It appears that there may be some indirect dependence on RuleCondition as well as other structures. I found this out while trying to explain the problem to WRI technical support.

In all cases, these answers should be a number (1. or 2.) followed by answers with that same number in a list. The spots where the number has extra zeroes indicate a rule that went unused when it should have been. Note the difference between the second to last cases for 1. vs. 2., which appear to depend on the use of RuleCondition and the size of the number (which affects the SameQ code).

In[1]:= $Version
Out[1]= "10.0 for Microsoft Windows (64-bit) (June 29, 2014)"

In[2]:= 1`5 /. {1`5 :> 1.}
Out[2]= 1.

In[3]:= {1`5} /. {1`5 :> 1.}
Out[3]= {1.0000}

In[4]:= {1`5} /. {1`5 :> 1. + 0}
Out[4]= {1.}

In[5]:= {1`5} /. {1`5 :> 1. + $MachineEpsilon}
Out[5]= {1.}

In[6]:= Block[{Internal`$SameQTolerance = -Infinity}, {1`5} /. {1`5 :>1. + $MachineEpsilon}]
Out[6]= {1.}

In[7]:= Block[{Internal`$SameQTolerance = -Infinity}, {1.`5} /. x_Real :> RuleCondition[N[x] + $MachineEpsilon, True]]
Out[7]= {1.}

In[8]:= Block[{Internal`$SameQTolerance = -Infinity}, {1.`5} /. x_Real :> N[x] + $MachineEpsilon]
Out[8]= {1.}

In[9]:= 2`5 /. {2`5 :> 2.}
Out[9]= 2.

In[10]:= {2`5} /. {2`5 :> 2.}
Out[10]= {2.0000}

In[11]:= {2`5} /. {2`5 :> 2. + 0}
Out[11]= {2.}

In[12]:= {2`5} /. {2`5 :> 2. + $MachineEpsilon}
Out[12]= {2.}

In[13]:= Block[{Internal`$SameQTolerance = -Infinity}, {2`5} /. {2`5 :>2. + $MachineEpsilon}]
Out[13]= {2.}

In[14]:= Block[{Internal`$SameQTolerance = -Infinity}, {2.`5} /. x_Real :> RuleCondition[N[x] + $MachineEpsilon, True]]
Out[14]= {2.0000}

In[15]:= Block[{Internal`$SameQTolerance = -Infinity}, {2.`5} /. x_Real :> N[x] + $MachineEpsilon]
Out[15]= {2.}