4 ms·
This is true for all languages, not just Python. Unfortunately C++ STL does not offer anything close to isclose (boost does however). Neither does Java. Float.
by cuteboy19 5y ago
This is true for all languages, not just Python.
Unfortunately C++ STL does not offer anything close to isclose (boost does however). Neither does Java. Float.compare is just == in disguise.
But while going through the docs I stumbled upon this Gem
> If f1 and f2 both represent Float.NaN, then the equals method returns true, even though Float.NaN==Float.NaN has the value false.
https://docs.oracle.com/javase/7/docs/api/java/lang/Float.html https://docs.oracle.com/javase/7/docs/api/java/lang/Float.ht...
- saurik 5y ago> But while going through the docs I stumbled upon this Gem You make it sound like that's crazy or something but the goal of .compare is to be used as a "comparator" to provide an ordering of all possible values in the implementation of various data structures or sorting algorithms, while the goal of the various operators is to support programmatic logic.
- cuteboy19 5y agoWe need a little bit of background for this. In Java the == operator checks if two variables are pointing to the same object. The .equals() method checks for actual value equality. new String("Hi")==new String("Hi"); // False new String("Hi").equals(new String("Hi")); // True Except for primitives like ints and floats where == does value comparison. 1==1;// True For NaN the value comparison is false. Even then .equals returns true Float.NaN==Float.NaN; // False new Float(0f/0f).equals(new Float(0f/0f)); // True!!!
- mlochbaum 5y ago> This is true for all languages, not just Python. Not quite: APL does comparisons with a configurable relative tolerance, which is nonzero by default. My article [0] about comparing one number to many quickly in this system starts with a discussion of the reasoning and mathematics there. It brings a lot of implementation difficulty, particularly with hash tables. It's possible to build a hash on tolerant doubles by making two hashes per lookup, and even complex numbers with four per lookup, but no one's figured out how to deal with entries that contain multiple numbers yet. Nonetheless I would say it does make it easier to write working programs overall. But not by much: I've been working on an APL derivative and initially left out comparison tolerance as there were some specifics I was unsure of. A year or so later I noticed I hardly ever needed it even for numerical work and dropped any plans to add it to the language. [0] https://www.dyalog.com/blog/2018/11/tolerated-comparison-part-1/ https://www.dyalog.com/blog/2018/11/tolerated-comparison-par...
- psykotic 5y ago> It's possible to build a hash on tolerant doubles by making two hashes per lookup, and even complex numbers with four per lookup, but no one's figured out how to deal with entries that contain multiple numbers yet. I'm curious what obstacle you have in mind for "multiple numbers". The problem is equivalent to a distance query on a data structure, i.e. enumerate everything within a distance tol of a query point x in an appropriate distance metric. There are many data structures for this problem (it's a basic building block in computational geometry). But I assume the hashing solution you have in mind is what we usually call a hash grid in gamedev and graphics, which works well when tol is fixed for the lifetime of the data structure. [1] Namely, you define a grid with cell size tol and map a point x to the index cell(x) of its containing cell, which is just a rounding operation. Then you can use a hash table keyed by cell(x) to store the contents of an unbounded, sparse grid. To perform a distance query from x you need to check not just x's cell but some of the immediately neighboring cells and then filter all of those candidates based on the pairwise distance. [2] [3] This approach works with any distance metric (including the usual suspects L^2, L^1 and L^inf) and in any dimension d although the worst-case number of cells to check in the hash is 2^d, so the curse of dimensionality is present and in high-dimensional spaces another data structure not based on rectilinear partitioning would be preferable. But hashing does work with "multiple numbers" if by "multiple numbers" you mean a vector (with not too many components) where tolerance is defined by a distance metric. [1] Actually, hash grids work well any time the query radius is on roughly the same scale as the cell size. But if the query radius is a lot smaller than the cell size then the grid is too coarse to perform adequate pre-filtering. And if the query radius is larger than the cell size you have to check a bigger neighborhood of cells (i.e. more hash lookups) to enumerate all the candidates. [2] Depending on the read vs write ratio, you can actually flip this around by storing each point in multiple cells so that queries only need one hash table lookup at the expense of slightly less precise pre-filtering. [3] Instead of doing multiple hash table lookups, you can also have each occupied cell store pointers to neighboring cells (null for unoccupied neighbors), which replaces hash table lookups for the neighbors with plain memory loads. A variation on this trick is to instead store bit flags to avoid doing hash table lookups for neighboring cells which are known to be empty; this takes up far less memory.
- PaulDavisThe1st 5y ago> Unfortunately C++ STL does not offer anything close to isclose maybe because you can trivially write it yourself with whatever precision you want: float a = 0.1; float b = 0.2; // now test for equality to within half of the smallest // value float can represent bool equal = fabs (0.3 - (a + b)) < (FLT_EPSILON/2); Alternatively: bool isclose (float v1, float v2, float prec = FLT_EPSILON/2) { return fabs (v1 - v2) < prec; } Variations are left to the reader. There are a few optimizations one can do but this version conveys the basic point: you get to specify the semantics of isclose()