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