go ahead... be a heretic PerlMonks

### Re^2: &1 is no faster than %2 when checking for oddness. Oh well. (range)

by tye (Sage)
 on Nov 16, 2006 at 06:45 UTC Need Help??

I went out to 11 digits and found that %2 was usually a lot more correct than &1, and I didn't have to do it millions of times and use a timer just to be able to notice. q-:

- tye

• Comment on Re^2: &1 is no faster than %2 when checking for oddness. Oh well. (range)

Replies are listed 'Best First'.
Re^3: &1 is no faster than %2 when checking for oddness. Oh well. (range)
by BrowserUk (Patriarch) on Nov 16, 2006 at 07:15 UTC

That's just a bug. Or it should be considered one.

```Perl> use Devel::Peek;;
Perl> \$n = 9_999_999_998; print Dump( \$n ); print \$n & 1; print Dump(
+\$n );;

SV = NV(0x1844044) at 0x19920c4
REFCNT = 1
FLAGS = (NOK,pNOK)
NV = 9999999998

1
SV = PVNV(0x1985a0c) at 0x19920c4
REFCNT = 1
FLAGS = (NOK,pIOK,pNOK,IsUV)
UV = 4294967295
NV = 9999999998
PV = 0

The silent 'promotion' of the NV to an UV with data loss is very messy.

It's also kinda schizophrenic when you consider that perl does differentiate between integer and real operations some places. Take the arbitrary and intensely annoying case of:

```Perl> \$c++ for 1 .. 2**32;;
[Range iterator outside integer range at (eval 7) line 1, <STDIN> line
+ 3.

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

I don't understand. Are you asserting that it is a bug that 1e11 & 1 doesn't die (or fail in some other way)? If so, then you didn't counter my point that %2 works for a ton more cases than &1. No, %2 doesn't work on huge numbers that don't fit accurately into an NV (but does work on huge numbers when you use an appropriate format for the huge numbers) nor on Russian words nor JPEG images. And, yes, writing "2" as "1.99..." leads to surprises. Of course, &1 doesn't fair any better on these straw men.

Or are you asserting that &1 should work directly on NVs? That'd be a non-trivial design change, so I wouldn't casually call that a "bug". If that were implemented in a way that made &1 work for detecting odd NVs, then it'd probably at least make it easier to see the speed difference between it and %2 (but then you'd be forced to use %2 anyway because it'd be trivially faster, I bet).

I'm shocked people can spend so much effort just trying to see if there is a speed difference between the two when it so clearly obvious (because it is so hard to even see a difference) that any difference that there is doesn't matter in the slightest.

I use %2 because 11- and 16-digit numbers are real, practical, useful things to be able to deal with right now (and I can even upgrade to some module for even bigger numbers with no changes). It is a "best practice" and most of the time works great (it always works great unless you have other problems, like using inappropriate storage for the numbers you are dealing with).

&1 often works but has zero real advantages (the speed difference, if anyone manages to show that there even is one, is of no consequence, even in fanciful extreme situations), except for people who can't equate "even" with "divisible by two" with "has 0 remainder when divided by two" and are only comfortable with equating "even" with "has some bit unset" (in what representation?).

Using &1 means that your code won't work when someone uses it with a perfectly valid Perl number that doesn't happen to fit in a UV. That is a real, practical disadvantage.

/me regrets having posted this already.

Enjoy.

- tye

/me too.

Why is it that you can never state your position without denigrating those who's opinion differs?

Others may allow you to get away with your unveiled ad homonym attacks and overbearing sarcasm, but whether they are aimed at me or others, I will call you on it every time.

I've explained my preference for my choice elsewhere in this thread, but nowhere have I attributed it to performance. The issue of performance is purely one of countering a bad benchmark. Nothing more.

Which makes "(but then you'd be forced to use %2 anyway because it'd be trivially faster, I bet)." nothing but another example of your overbearing sarcasm.

I'm shocked people can spend so much effort just trying to see if there is a speed difference between the two when it so clearly obvious (because it is so hard to even see a difference) that any difference that there is doesn't matter in the slightest.

Again. You attribute me with motives for which there is no basis. I didn't post the original benchmark. I simply drew attention to its flaws and cleaned it up.

even in fanciful extreme situations)

More denigration. Once again based upon nothing in this thread.

people who can't equate "even" with "divisible by two" with "has 0 remainder when divided by two" and are only comfortable with equating "even" with "has some bit unset"

Why use the word "comfortable"? It certainly isn't derived from anything I've said in this thread. Nor anything anyone else has said that I've read. Again, you attempt to make the arguments personal instead of technical. For what purpose?

Using &1 means that your code won't work when someone uses it with a perfectly valid Perl number that doesn't happen to fit in a UV.

If I use & 1 in my code, it is because I know that values I am applying it to are integers that will not exceed that range of values to which the application of bit-wise operators can be applied. That is a part of my job as a programmer.

If someone else comes along and takes that code and utilises it in a situation where that does not hold true, then it is their job as programmers to recognise that and adjust the code accordingly. (See below!)

If your argument is that I should not be aware nor care what storage format is used to represent numbers and should always code such that all operations can be applied to the full range of Perl's numeric representations, why does perl have bitwise numeric operations? There is no logical way they could ever be used in those circumstances!

You say "it always works great unless you have other problems, like using inappropriate storage for the numbers you are dealing with).", but how is using

```\$n = 9_007_199_254_740_992; print 'Even' unless \$n % 2;;
Even

"appropriate", but not

```++\$n; print 'Even' unless \$n % 2;;
Even
Are you asserting that it is a bug that 1e11 & 1 doesn't die (or fail in some other way)?

Yes.

Are you seriously suggesting that you would design a new language that silently converts 99_999_999_999 into 4294967295?

So, despite another piece of your sarcasm addressed to a straw man of your own construction "Or are you asserting that &1 should work directly on NVs?", that again appears nowhere else in the thread.

Yes, I am suggesting that perl's silent conversion of 99_999_999_999 into 4_294_967_295 is a bug. It may be a behaviour that will never change due to backward compatibility, but I cannot believe it was a deliberate design decision, and that makes it a bug.

The greater range that one method continues to work over (before again silently failing), is pretty irrelevant on two counts.

1. For the great majority of applications that use oddness tests, the range of an IV or UV is more than sufficient. Think carefully about that statement, from the perspective of real code, rather than the hypothetical.

If attempting to "future proof" applications by using NVs where we know IVs or UVs were more than sufficient was a good idea.

• Why do we bother with IVs and UVs at all?
• Why don't we use bignum in every script we write?
2. Most importantly, if I have chosen to use & on a particular variable for this purpose--because I know it is sufficient for this purpose--then it's quite possible, even likely that I will have
• used other boolean operations on that same variable for other purposes.
```my( \$loWord, \$hiWord ) = ( \$n & 0xffff, \$n >> 16 );
• Or use pack or unpack on that variable.
```print unpack 'N', pack 'N', 99_999_999_999;;
4294967295
• Or used (s)printf on that variable;
```printf "%d\n", 99_999_999_999;;
-1
• Or used my knowledge of the size of that variable in some math somewhere.
```my \$indexSize = 4 * \$noLines;
• Or any number of other operations that require that variable to be a 32-bit integer of one form or other.

If I code a 'oddness' test on that variable using % 2 somewhere in the code, then I am asking for the next guy that comes along and sees that to assume that extending the range of use for that variable is safe. When I know it is not.

This is the exact counter argument to your

Using &1 means that your code won't work when someone uses it with a perfectly valid Perl number that doesn't happen to fit in a UV. That is a real, practical disadvantage.

By using & 1 for oddness testing, I am clearly flagging the intended design range for the variable. Using % 2 would be to conceal that information.

The bottom line with this, as with so many "future proofing" arguments, is that you cannot predict the future, and trying is futile as it creates as many potential problems as it potentially solves. You cannot protect the future programmer against the effects of the changes they might make.

It is, and must be incumbent on the future/maintenance programmer to understand the code he is modifying before he makes his modifications. And all the arguments that suggest that you can prevent future problems by allowing the programmer to leap in and make changes without fully understanding their implications, are bogus.

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://584386]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (2)
As of 2024-04-20 10:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?

No recent polls found