Skip to content

Instantly share code, notes, and snippets.

@mikesamuel
Created November 14, 2023 20:56
Show Gist options
  • Save mikesamuel/479bd1b276f43ac46302b546bec04998 to your computer and use it in GitHub Desktop.
Save mikesamuel/479bd1b276f43ac46302b546bec04998 to your computer and use it in GitHub Desktop.
JS cmp function sorting NaN high and distinguishing zeroes
function cmpNums(a, b) {
if (Object.is(a, b)) { return 0; }
let delta = a - b;
if (delta) {
return Math.sign(delta);
} else if (delta === 0) {
// The only values that do not match Object.is above
// and which do not lead to a NaN delta are -0, +0
// and vice versa.
return Object.is(a, -0) ? -1 : 1;
} else {
// delta is NaN which is the case for
// NaN, notNaN
// notNaN, NaN
// -Infinity, Infinity
// Infinity, -Infinity
// Sort NaN high
if (a !== a) {
return 1;
} else if (b !== b) {
return -1;
}
// comparing infinities
return Math.sign(a) - Math.sign(b);
}
}
// Dump a table of pairwise comparison results to the console.
// The diagonal should have '=' and the two sides should be
// filled with `<` and `>` respectively.
function test() {
function dumpTables(rows) {
let n = rows.length;
let str = '';
for (let j = 0; j < n; ++j) {
let row = rows[j];
for (let m = row.length, i = 0; i < m; ++i) {
if (i) {
// Separate cells with bars.
// Double bar after the header cell.
str += i === 1 ? " || " : " | ";
}
str += row[i];
}
if (j === 0) {
// Line of ====== under the header row.
str += "\n" + str.replace(/[\s\S]/g, "=");
}
str += "\n";
}
return str;
}
let importantValues = [-Infinity, -1, -0, 0, 1, Infinity, NaN];
let importantValuesWithHeader = [null, ...importantValues];
let importantValueToStrMap = new Map([
[-Infinity, "-inf"],
[-1, "-001"],
[0, "+000"],
[1, "+001"],
[Infinity, "+inf"],
[NaN, "_nan"],
]);
function importantValueToStr(x) {
if (Object.is(x, -0)) { return "-000"; }
return importantValueToStrMap.get(x);
}
function cmpResultStr(delta) {
switch (delta) {
case -1: return " < ";
case 0: return " = ";
case 1: return " > ";
}
}
let rows = importantValuesWithHeader.map((b) => {
if (b == null) {
// Header row
return importantValuesWithHeader.map(
(a) => a === null ? 'cmp ' : importantValueToStr(a)
);
}
return [importantValueToStr(b), ...importantValues.map(
(a) => cmpResultStr(cmpNums(a, b))
)];
});
console.log(dumpTables(rows));
}
test();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment