lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Coda Highland once stated:
> On Fri, Apr 24, 2015 at 7:21 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> > 2015-04-24 15:41 GMT+02:00 Egor Skriptunoff <egor.skriptunoff@gmail.com>:
> >
> >> Yes, we have strange results when sorting tables with NaNs inside.
> >> But we don't have errors there.
> >> Is it possible to receive "invalid order function for sorting" error for
> >> default sorting (using default order function) of a table filled with mixed
> >> integer/float values due to non-transitivity of default operator ">="?
> >>
> >> Transitivity of equality and relational operators sits very deep in our
> >> brains.
> >> A language without such transitivity would be counter-intuitive,
> >> programming on it would be error-prone.
> >>
> >> IMHO, if both numbers are inside range 2^53...2^63, they should be compared
> >> using conversion to integers, despite of possible performance penalty.
> >
> > Didn't Roberto say just that? Let me find it ...
> >
> > | (In terms of implementation, it means that integer-float should be
> > | compared converting the float to an integer; if the conversion fails,
> > | the numbers cannot be equal.) That definition is simple, sounds
> > | sensible and easy to explain, and makes equality transitive.
> >
> 
> That doesn't help with the issue of nontransitivity of >, only ==: if
> the conversion fails, which number is "less"?
> 
> /s/ Adam

  To illustrate this point:

	#include <stdio.h>

	int main(void)
	{
	  int x;
	  
	  for (x = 268435456 ; x < 536870912 ; x++)
	  {
	    float f = x;
	    int   y = f;
	    printf("%d %d %d\n",x,y,x-y);
	  }
	   
	  return 0;
	}

  I used 'float' here because it's smaller and therefore, makes it easier to
wrap my brain around the values used.  Also, the code here assumes
sizeof(int) == sizeof(float) (both 32 bits).  A float can support integers
up to 2^23 without issue, but past that, things get interesting.  I start
with 2^28 and sure enough, I saw what I was expecting to find:

	268435473 268435488 -15
	268435474 268435488 -14
	268435475 268435488 -13
	268435476 268435488 -12
	268435477 268435488 -11
	268435478 268435488 -10
	268435479 268435488 -9
	268435480 268435488 -8
	268435481 268435488 -7
	268435482 268435488 -6
	268435483 268435488 -5
	268435484 268435488 -4
	268435485 268435488 -3
	268435486 268435488 -2
	268435487 268435488 -1
	268435488 268435488 0
	268435489 268435488 1
	268435490 268435488 2
	268435491 268435488 3
	268435492 268435488 4
	268435493 268435488 5
	268435494 268435488 6
	268435495 268435488 7
	268435496 268435488 8
	268435497 268435488 9
	268435498 268435488 10
	268435499 268435488 11
	268435500 268435488 12
	268435501 268435488 13
	268435502 268435488 14
	268435503 268435488 15

(268435473 is only 17 more than the starting value.)

If you follow it out, you'll notice a pattern---past 2^32, the "spread" of
the integers becomes 2^(32-(log2(x)-1)).  Since we start with 2^28, our
"spread" is 32:

		2^(32-(log2(268435486)-1))
		2^(32-(28+1))
		2^(32-27)
		2^(5)
		32

Makes sense when you think about it.  Even more interesting is this bit of
code:

	#include <stdio.h>
	
	int main(void)
	{
	  float    f = 8589934592.0; /* 2^33 */
	  int      x = f;      
	  unsigned y = f;
	
	  printf("%f %d %u\n",f,x,y);
	  return 0;
	}

(Again, assumption is sizeof(int) == sizeof(float).)

The results here have me perplexed because the output is not what I
expected:

	8589934592.000000 -2147483648 0

Truthfully, I'm not sure what I expected, but two wildly different answers
isn't it; perhaps INT_MAX and UINT_MAX but not INT_MIN and 0!  2^31 gave the
expected answers, and 2^32 gave -2147483648 0.  

  -spc (While I like the 64-bit integer support in Lua 5.3, I'm not sure if
	I like the quiet conversions behind the scenes ... )