Richard Cornford wrote:
> RobG wrote:
>
[...]
>
> Irrelevant if you have to do that anyway.
The strategy is to emulate ceil/floor, i.e. ensure that +ve numbers are
always 'rounded' up and -ve always 'rounded' down. This can be done by
adding 1 to +ve and subtracting 1 from -ve and truncating. The trick is
to do the logic for determining +ve/-ve, add/subtract and truncate with
the quickest algorithm.
I want numbers like 0.1 to become 1 (add 1 and truncate or use ceil) and
-0.1 to become -1 (subtract 1 and truncate or use floor).
It seems simply adding/subtracting and letting the browser truncate when
setting style.left/top is not reliable - small 'jitters' occur randomly
near the end of the movement, different browsers have different
behaviours. I was pretty sure I'd be told to pass integers.
>>than Math.ceil/floor. Naturally I'd like to use that since
>>it's so much quicker.
>
>
> Subtraction is no substitute for rounding.
In the context described above, it kinda works, but not reliably, so I
guess you're right.
[...]
>
> No. Many browsers will happily make pixel approximations of non-integer
> values (they need to in order to cope with em, %, etc. units), but some
> go belly up. It is much safer only to ask for pixel positions in
> integers.
Agreed, and the results are inconsistent across browsers so it's a poor
strategy - unless unpredictable jitters with imprecise movement are
intended.
>>or should I be making x an integer first (using
>>parseInt or Math.ceil/floor)?
>
> <snip>
>
> No. If you want to turn a number with a fractional part into an integer
> suitable for use in positioning in the quickest way possible use:-
>
> x | 0
>
> - or:-
>
> x >> 0
>
> - as the bitwise operations truncate their operands to 32 bit signed
> integer values (except for - >>> -, which uses ToUint32 internally
> instead of ToInt32). 32 bit signed integers are sufficiently big to cove
> all realistic pixel positioning and dimension requirements.
Here's my final version. moveBy is generated by some function of the
distance between two elements:
if ( moveBy ) {
setPos( obj, ((moveBy > 0)? ( moveBy+=1 | 0 ) : ( moveBy-=1 | 0 ) ));
}
It's neatly symmetrical, fast and +ve/-ve movement and truncating are
dealt with in one go.
Which is at least as fast as simply adding/subtracting one and is faster
by a factor of about 15 than the equivalent:
setPos( obj, ((moveBy > 0)? Math.ceil(moveBy) : Math.floor(moveBy)));
>
> Generally, if you want fast math for pixel positioning work try to use
> bitwise operators, particularly at the end of sequences of calculations.
> For example, halving a dimension can be done as - ( x >> 1 ) - and be
> guaranteed to return an integer result (so will not then need to be
> floored), so:-
>
> ((totalWidth - elementWidth) >> 1)
>
> - gives you a guaranteed integer result that is no bigger than half of
> the width not taken up by elementWidth, ideal for centring an element in
> a space, and without the need for further rounding.
Yes, but I need to account for direction (+ve -ve) and would like to
have that done within a single step as above.
>
> <snip>
>
>> i = this.form.num.value;
>> s = new Date();
>> while ( i-- ) {
>> ( x>0 )? parseInt(x)+1 : parseInt(x)-1;
>
> <snip>
>
> It is difficult for me to tell what you are after from this. My
It's just a test of part of my logic, on its own it's pretty
meaningless. ;-p
[...]
>
> Many expressions can be used to give +1/-1 results based on
> Math.random(), E.G.:-
>
> Math.random()<0.5 ? +1 : -1 // fastest on average, by a
> // small margin
>
> (((Math.random()<0.5)&& +1)||-1)
>
> ((Math.random()+0.5)<<1)-1
>
> ((Math.random()<0.5)<<1)-1
>
> So given a positive distance - d - that starts truncated/floored to an
> integer, but must be made at least 1, and a direction - v -, that will
> be either -1 or +1, you might have:-
>
> (d + !d) * v
>
> - where if - d - is non-zero - !d - is false, adding zero after
> type-conversion to a number, and when - d - is zero - !d is true, adding
> 1 following type-conversion. Then the dimensions - d -,
> truncated/floored and adjusted by one,if needed, only in one direction,
> is multiplied by +1 or -1 to give an integer distance in one of two
> opposite directions.
Actually I'm trying to avoid random movement (!) but thanks for the tip,
I'm sure it will come in handy.
--
Rob