Improve StrUtils.NaturalCompareText.
Counterexamples to the current implementation:
NaturalCompareText('100000000000000000000', '100000000000000000001') = 0
because of double
; must be −1.
NaturalCompareText(' 10 hi', '010 hi') = 0
— kept as a feature, BUT:
NaturalCompareText('score: 10', 'score:010') = 1
— my version considers such spaces as parts of numbers to be consistent with what it does at the beginning of the string, so will return 0 again.
NaturalCompareText('9', ' ') = 0
— has bad consequences, because...
const
A = '3';
B = ' '; // two spaces
C = '2 a';
NaturalCompareText(A, B) = -1 // A < B...
NaturalCompareText(B, C) = -1 // and B < C...
NaturalCompareText(A, C) = 1 // but A > C ?!
— such handling of spaces makes comparisons intransitive, which can break or even crash certain algorithms.
Not sure about complete transitiveness of my implementation either, but at least I didn’t manage to find any counterexamples with fuzzing. And it still ignores ADecSeparator
and AThousandSeparator
(doable though).
NaturalCompareText('A', '') = <GARBAGE>
On i386-win32
, simple writeln(NaturalCompareText('A', ''))
writes something like 4200096 consistently enough for me, but in general can be hard to reproduce on purpose. Looking at the code reveals the reason: Result
is uninitialized when any of the inputs is empty.