Anyone got a good maths head?

Blitz3D Forums/Blitz3D Programming/Anyone got a good maths head?

D4NM4N(Posted 2006) [#1]
Need a very quick way of averaging 2 32bit argb hex numbers:

ie:
print averagehex($FFFFFFFF,$00000000)
returns:
$80808080
I can do i by breaking it down but may be a bit slow for what i need


GfK(Posted 2006) [#2]
Hex is only a way of representing a number, so you can use the following:

Print Hex((n1+n2)/2)


D4NM4N(Posted 2006) [#3]
wont that cause a 32bit integer overflow


BlackJumper(Posted 2006) [#4]
First up, the average above should be $80000000 (or $7FFFFFFF if rounding down)

Next, you can treat each hex digit completely separately due to the x16 nature of each 'nybble' which will half exactly when averaging.

so... any scheme which averages each hex pair can be used as long as the strings are the same length

option 1: add the two digits and half them {problem... you need to add 'letter' digits}

option 2: given any two digits, move progressively towards the 'middle' value by +1 to lowest and -1 to highest until they meet.

I don't have time to code one, but I think you should be able to work one up from here...

{That lot off the top of my head, so I wouldn't bet the mortgage on it... e.g. the bit about separating digits might be subject to revision where 'rounding' occurs or where they don't 'meet' but cross over instead}


GfK(Posted 2006) [#5]
Might if you're using stupidly high numbers, but for the most part it'll work. Alternatively try Print Hex(n1+(n2/2)).

Don't have Blitz on this PC so I can't test stuff.

[edit]Also depends whether you want median or mean average. They aren't the same.


D4NM4N(Posted 2006) [#6]
80000000! (oh yeah... (slap on head) :)
thats what i thought, ive done it byte for byte. It wasnt as slow as i thought itd be :P

thanks


D4NM4N(Posted 2006) [#7]
"Might if you're using stupidly high numbers, but for the most part it'll work. Alternatively try Print Hex(n1+(n2/2))."

I am using stupidly high numbers ;)


BlackJumper(Posted 2006) [#8]
Alternatively try Print Hex(n1+(n2/2))


misplaced bracket in there !

Alternatively try Print Hex((n1+n2)/2)


GfK(Posted 2006) [#9]
misplaced bracket in there !

Nope. I want to divide n2 first. Its correct.


BlackJumper(Posted 2006) [#10]
@GfK:
n1 = 4; n2 = 6 .... average is 5

but n1 + (n2/2) = 4 + 6/2 = 4 + 3 = 7

.... I beg to differ !

(n1 + n2)/2 = (4 + 6)/2 = 10/2 = 5


GfK(Posted 2006) [#11]
Well maybe the maths was wrong (I did say I hadn't tested it at all), but its as I intended it at the time.

Should've been n1+((n2-n1)/2)


PGF(Posted 2006) [#12]
avg(a,b) = (a + b) / 2 = a/2 + b/2

When using integer arithmetic you have to be careful of the rounding in intermediate results.

So:

a:Int = 1234567
b:Int = $12345678

Print Hex((a + b) / 2) ' Simplistic but may overflow
Print Hex((a shr 1 + b shr 1)) ' Close but may be out by 1

' This is the correct solution
Print Hex(a Shr 1 + b Shr 1 + ((a & $01) + (b & $01)) Shr 1)


PGF(Posted 2006) [#13]
The above is expressed in BlitzMax as I don't have Blitz3D. The syntax will not work exactly but the intent certainly should.

(Note to self - check which forum the post is in)


BlackJumper(Posted 2006) [#14]
That's a very nice solution PGF... the bitmask part on the end is very elegant.