<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Feb 5, 2015 at 2:46 PM, Andrew Barnert <span dir="ltr"><<a href="mailto:abarnert@yahoo.com" target="_blank">abarnert@yahoo.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">>Non-float types<br>
>---------------<br>
><br>
>The primary use-case is expected to be floating point numbers.<br>
>However, users may want to compare other numeric types similarly. In<br>
>theory, it should work for any type that supports ``abs()``,<br>
>comparisons, and subtraction.  The code will be written and tested to<br>
<br>
>accommodate these types:<br>
<br>
</span>Surely the type also has to support multiplication (or division, if you choose to implement it that way) as well, right?<br></blockquote><div><br></div><div>yes, multiplication, not sure how I  missed that. No division necessary.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Also, are you sure your implementation doesn't need any explicit isinf/isnan checks? You mentioned something about cmath.isnan for complex numbers.<br></blockquote><div><br></div><div>yeah, there's that. Though it seems to work fine for Fraction and Decimal so far -- I'm taking a TDD approach -- if it works with a test, I don't worry about it ;-)</div><div><br></div><div>This brings up a bigger issue, that I'm pretty nuetral on:</div><div><br></div><div>What to do about duck-typing and various types it may get called with? My intent was to count of duck typing completely:</div><div><br></div><div>1) I'll test with the types I mentioned in the PEP (I need a few more tests to be rigorous)</div><div><br></div><div>2) For any other type, it may work, it may not, and hopefully users will get an Exception, rather than a spurious result if it doesn't.</div><div><br></div><div>I can't possible test with all types, so what else to do?</div><div><br></div><div>Would datetime.timedetla be worth explicitly supporting? the concept of a two datetimes being relatively close doesn't make any sense -- relative to what???? And abs() fails for datetime already. I'll check timedelta -- it should work, I  think -- abs() does anyway.</div><div><br></div><div>I'm a bit on the fence as to whether to do type dispatch for Decimal, as well -- there are some oddities that may require it.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Presumably this is just copying assertAlmostEqual and replacing the element comparisons with a call to isclose, passing the params along?</blockquote><div><br></div><div>yup -- but worth it? Maybe not.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">>How much difference does it make?<br>
<br>
>---------------------------------<br>
<br>
</span>This section relies on transformations that are valid for reals but not for floats. In particular:</blockquote><div><br></div><div>does this effect the result? I also assumed a and b are positive and a>b, just to make all the math easier (and easier to write). I'm not really trying to do a proper rigorous formal proof here. And it does check out computationally -- at least with comparing to 1.0, there is no floating point value that passes some of the test, but not others with a rel_tol of 1-e9 (there is one value that does for 1e-8)</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
>  delta = tol * (a-b)<br>
><br>
>or::<br>
><br>
>  delta / tol = (a-b)<br></span></blockquote><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">If a and b are subnormals, the multiplication could underflow to 0, but the division won't; </blockquote><div><br></div><div>there is no division in the final computation anyway -- I only understand enough FP to barely pass a class with Kahan, but I think it's OK to do the derivation with real numbers, and then check the FP consequences with the actual calculation in this case.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">if delta is a very large number, the division could overflow to inf but the multiplication won't. (I'm assuming delta < 1.0, of course.) Your later substitution has the same issue. I think your ultimate conclusion is right, but your proof doesn't really prove it unless you take the extreme cases into account.<br></blockquote><div><br></div><div>I"m not sure all that needs to be in the PEP anyway -- it's jsut that thre was a lot of discussion about the various methods, and I had hand-wavingly said "it doesn't matter for small tolerances" -- so this is simply making that point for formally.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class="">>The case that uses the arithmetic mean of the two values requires that<br>
>the value be either added together before dividing by 2, which could<br>
>result in extra overflow to inf for very large numbers, or require<br>
>each value to be divided by two before being added together, which<br>
<br>
>could result in underflow to -inf for very small numbers.<br>
<br>
</span>Dividing by two results in underflow to 0, not -inf. </blockquote><div><br></div><div>oops, duh. thanks.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Also, dividing by two only results in underflow to 0 for two numbers, +/-5e-324, and I don't think there's any case where that underflow can cause a problem where you wouldn't already underflow to 0 unless tol >= 1.0, so I'm not sure this is actually a problem to worry about. </blockquote><div><br></div><div>no -- not really -- being a bit pedantic ;-)</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">>Relative Tolerance Default<br>
>--------------------------<br><br>
This section depends on the fact that a Python float has about 1e-16 precision.</blockquote><div><br></div><div>indeed.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> But technically, that isn't true; it has about sys.float_info.epsilon precision, which is up to the implementation; CPython leaves it up to the C implementation's double type, and C89 leaves that up to the platform. That's why sys.float_info.epsilon is available in the first place--because you can't know it a priori.<br><br>
In practice, I don't know of any modern platforms that don't use IEEE double or something close enough, so it's always going to be 2.2e-16-ish. </blockquote><div><br></div><div>that's what I was assuming -- but I guess there is always micropython -- does it have machine doubles? I assume the common mobile platfroms do -- but what do I know?</div><div> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">And I don't think you want the default tolerance to be platform-dependent. And I don't think you want to put qualifiers in all the half-dozen places you mention the 1e-9. I just think it's worth mentioning in a parenthetical somewhere in this paragraph.<br></blockquote><div><br></div><div>Good idea. </div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
>default of 0.0 is selected.<br>
<br>
</span>Does that default work properly for the other supported types?</blockquote><div><br></div><div>see above for the duck-typing question -- it does work for all the types I've tested with.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> Maybe it's better to just specify "zero" and leave it up to the implementation to do the trivial thing if possible or something more complicated if necessary, rather than specifying that it's definitely the float 0.0?<br></blockquote><div><br></div><div>done in the PEP.</div><div> </div><div>Thanks for the typo fixes.</div><div><br></div><div>-Chris</div><div><br></div></div><div><br></div>-- <br><div class="gmail_signature"><br>Christopher Barker, Ph.D.<br>Oceanographer<br><br>Emergency Response Division<br>NOAA/NOS/OR&R            (206) 526-6959   voice<br>7600 Sand Point Way NE   (206) 526-6329   fax<br>Seattle, WA  98115       (206) 526-6317   main reception<br><br><a href="mailto:Chris.Barker@noaa.gov" target="_blank">Chris.Barker@noaa.gov</a></div>
</div></div>