I'm looking for a simple algorithm that reliably chooses the same 'winner' from 2 or more different numbers. There's no guarantees about the order in which you receive the numbers (but they can be sorted or something similar). An easy way of solving this would be picking the largest/smallest number, however this is not a very fair algorithm as it heavily favors large/small numbers.
The algorithm does not have to be perfect and may perform bad with few limited numbers, I thought of calculating hashes but this takes too much cpu time and want to stick to simple additions/multiplications/mod, it should remain simple.
follow up question is if there's a class of algorithms dedicated to this subject?
Thanks in advance!
Expanding comments to an answer...
I think what you want is a rough and ready "hash", which you can generate at low cost.
The following suggestions are designed to compare two "number"s to give an entirely deterministic, but not obvious ordering. To do that this extracts an n-bit "rank" for each "number" to be compared, then compares the "rank"s. If two "number"s have the same rank, then need to break the tie by comparing the "numbers" directly.
Using Multiplication
If your CPU has a fast n-bit multiply, then a good Linear Congruent pseudo-random number generator (with modulus 2^n) (LCG) will give a nicely random looking "rank" for each "number", at the cost of a single multiply.
The process is, then:
"munge" each "number" to an n-bits
If the "number" is more than n-bits long (you mention mac-address) then the first step is to munge that into n-bits. Start with "rank" set to something-large-and-random-looking (as many digits of pi, or e, say, as will fit). Then xor in the "number" n-bits at a time, rotating the "munge" between xors (at least 1 bit, but any odd number of bits, ceiling(n/3), perhaps). The rotation retains a little flavour of the order in which the n-bit parts are munged in.
If the "number" is n-bits or less, starting with "munge" xor something-large-and-random-looking adds a little spice.
Construct the "rank" from each "munge".
Multiply the "munge" by a good n-bit LCG multiplier, to give the n-bit "rank".
Compare and tie break.
Compare the "rank"s, if they are not equal the process is complete.
With a good LCG it's probably unlikely that two "numbers" will give the same "rank" (unless you've only got a 16-bit multiply).
But in any case, if two "number"s do give the same "rank", then to break the tie you can fall back on comparing the numbers. To make that less obvious, you can xor each "number" with the "rank" before doing the comparison. This will work if more than two "number"s have the same "rank".
[Remember that the ls-bits of an LCG are less-random-looking than the ms-bits. Since this is only a tie-break that probably doesn't matter, but if it is natural to compare the "number"s byte-wise (for example) it would be better to use the ms-bits of the "rank".]
Using only XOR and Rotate
If multiplication is too slow, which these days is still true for (small) micro-controllers, then let us assume the "number" must be processed 8- or 16-bits at a time.
Starting with (say) "munge"=157 or "munge"=31415, step (1) above will not do a bad job, particularly if the "number" is three or or more n-bit units.
A final stir: setting "rank" to "munge" xor ("munge" rotated by ceiling(n/3)), won't hurt.
Then proceed as (3), above.
Using CRC
If the CPU has a (fast) hardware assisted n-bit CRC generator, then either:
or:
Then proceed as (3) above.