473,748 Members | 4,067 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Math.ceil/floor Vs parseInt Vs plus/minus


I am writing a script to move an absolutely positioned element on a
page by a factor using style.top & style.left.

The amount to move by is always some fraction, so I was tossing up
between Math.ceil/floor and parseInt +/- 1 to ensure the amount to
move was at least 1 and in the right direction. I made a small test to
see which one is faster and also included simply adding/subtracting 1.

parseInt generally took 50% to 100% longer than Math.ceil/floor, but
adding/subtracting 1 is 30 to 100 times faster (depending on the
browser) than Math.ceil/floor. Naturally I'd like to use that since
it's so much quicker.

So my question is:

Is it safe to set the 'top' or 'left' of an element to some
fractional measurement of pixels?

e.g. is it safe to do:

x = 1.9863098
el.style.left = x + 'px'

or should I be making x an integer first (using parseInt or
Math.ceil/floor)? Here's my test script:
<form action="">
<input type="text" value="1000" name="num">Numb er of iterations<br>
<textarea name="outCell" rows="10" cols="30">
Click Run it to run it.
</textarea>
<input type="button" value="Run it" onclick="

// x will sometimes be +ve, sometimes -ve
var x = (Math.random()-0.5)*10;
var i, f, s, t0, t1;

i = this.form.num.v alue;
s = new Date();
while ( i-- ) {
( x>0 )? parseInt(x)+1 : parseInt(x)-1;
x += x;
}
f = new Date();
t0 = f-s;

i = this.form.num.v alue;
s = new Date();
while ( i-- ) {
( x>0 )? Math.ceil(x) : Math.floor(x);
x += x;
}
f = new Date();
t1 = f-s

i = this.form.num.v alue;
s = new Date();
while ( i-- ) {
( x>0 )? x+1 : x-1;
x += x;
}
f = new Date();

this.form.outCe ll.value =
'parseInt: ' + t0 + '\n'
+ 'ceil/floor: ' + t1 + '\n'
+ 'plus/minus: ' + (f-s)
;
">
</form>
--
Rob
Jul 23 '05 #1
6 8775
RobG wrote:
I am writing a script to move an absolutely positioned element
on a page by a factor using style.top & style.left.

The amount to move by is always some fraction, so I was tossing
up between Math.ceil/floor and parseInt +/- 1 to ensure the
amount to move was at least 1 and in the right direction. I
made a small test to see which one is faster and also included
simply adding/subtracting 1.

parseInt generally took 50% to 100% longer than Math.ceil/floor,
It would as parseInt type-converts non-string arguments into strings
prior to parsing them.
but adding/subtracting 1 is 30 to 100 times faster (depending
on the browser)
Irrelevant if you have to do that anyway.
than Math.ceil/floor. Naturally I'd like to use that since
it's so much quicker.
Subtraction is no substitute for rounding.
So my question is:

Is it safe to set the 'top' or 'left' of an element to some
fractional measurement of pixels?

e.g. is it safe to do:

x = 1.9863098
el.style.left = x + 'px'
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.
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.

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.

<snip> i = this.form.num.v alue;
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
inclination would be to handle distance and direction independently.
Acquiring a +1/-1 value for direction and a separate positive value for
distance. That allows the distance to be rounded in a known directions
(ie, truncated with bitwise operators, floored or ceiled) and then
direction applied by multiplication with +1/-1 (preserving the integer
nature of the result).

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.

Richard.
Jul 23 '05 #2
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(moveB y) : Math.floor(move By)));

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.v alue;
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
Jul 23 '05 #3
RobG wrote:
<snip>
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 )
)); }

<snip>

In looking at this I observe that the value that is determined by the
outcome of the conditional expression is the +/-1, so maybe;-

setPos( obj, ((moveBy += ((moveBy > 0)?1:-1)) | 0) )

Richard.
Jul 23 '05 #4
Richard Cornford wrote:
RobG wrote:
<snip>
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 )
)); }


<snip>

In looking at this I observe that the value that is determined by the
outcome of the conditional expression is the +/-1, so maybe;-

setPos( obj, ((moveBy += ((moveBy > 0)?1:-1)) | 0) )


And the outer bit-wise truncates - sweet!
--
Rob
Jul 23 '05 #5
JRS: In article <Hq************ ******@news.opt us.net.au>, dated Fri, 8
Jul 2005 01:13:11, seen in news:comp.lang. javascript, RobG
<rg***@iinet.ne t.auau> posted :
Richard Cornford wrote:
RobG wrote:
<snip>
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 )
)); }


<snip>

In looking at this I observe that the value that is determined by the
outcome of the conditional expression is the +/-1, so maybe;-

setPos( obj, ((moveBy += ((moveBy > 0)?1:-1)) | 0) )


And the outer bit-wise truncates - sweet!


If you are repeatedly moving in the same direction by
function(distan ce), then the direction should be determined, for speed,
outside the move loop. Possibly, write a function to move +, another to
move -, and at the start of each sequence assign one or other to do the
job; but function calls may be slower.

If you are using new Date() to time your moves, you probably need not
care much about the speed of the move calculation code, depending on OS;
unless the OS maintains and serves the date as a day- or seconds- count,
there's more work in new Date() than there can be in move-calculation.
And, between ticks, one can calculate a lot.

Timing with setTimeout or setInterval would not have those overheads,
but different ones.

--
© John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 IE 4 ©
<URL:http://www.jibbering.c om/faq/> JL/RC: FAQ of news:comp.lang. javascript
<URL:http://www.merlyn.demo n.co.uk/js-index.htm> jscr maths, dates, sources.
<URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
Jul 23 '05 #6
Dr John Stockton wrote:
JRS: In article <Hq************ ******@news.opt us.net.au>, dated Fri, 8
Jul 2005 01:13:11, seen in news:comp.lang. javascript, RobG
<rg***@iinet.ne t.auau> posted :
Richard Cornford wrote:
RobG wrote:
<snip>

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 )
)); }

<snip>

In looking at this I observe that the value that is determined by the
outcome of the conditional expression is the +/-1, so maybe;-

setPos( obj, ((moveBy += ((moveBy > 0)?1:-1)) | 0) )

And the outer bit-wise truncates - sweet!

If you are repeatedly moving in the same direction by
function(distan ce), then the direction should be determined, for speed,
outside the move loop. Possibly, write a function to move +, another to
move -, and at the start of each sequence assign one or other to do the
job; but function calls may be slower.


Thanks, I'll consider that.

The destination can move before it is reached, therefore position and
distance are calculated each time after a move. I am working on
creating objects that learn to move of their own accord - accelerate,
move with a set speed, then decelerate. But they also need to be
updated with where the destination has moved to as they go.

My biggest speed issue is eliminating the use of Math functions. They
are handy to use to get the logic right, but then optimisation is
required - using a function that is 30 times faster frees-up quite a
bit of CPU!

If you are using new Date() to time your moves, you probably need not
care much about the speed of the move calculation code, depending on OS;
unless the OS maintains and serves the date as a day- or seconds- count,
there's more work in new Date() than there can be in move-calculation.
And, between ticks, one can calculate a lot.
I was using a date object to time sections of code - usually 10,000 or
so loops with multiple runs are required to get meaningful results.
I've also found that when testing a series loops in a single function,
going first is a distinct disadvantage.

Timing with setTimeout or setInterval would not have those overheads,
but different ones.

--
Rob
Jul 23 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
2493
by: Tom | last post by:
Has anyone ever seen a IComparer for floats the returns magnitude. i.e. instead of returning -1, it would return -5. To let you know HOW different the two numbers are. obviously for int it is a - b. But for float the results would have to be normalize some how to a 32bit range. I understand there would be percision errors. Thanks Tom
1
2741
by: limelight | last post by:
I have discovered a math error in the .NET framework's Log function. It returns incorrect results for varying powers of 2 that depend on whether the program is run from within the IDE or from the command line. The amount by which the calculation is off is very small; even though the double data type holds the errant value, it seems to round off when printed (via ToString()) and shows the correct one. The problem is that the errant value is...
4
5047
by: Henke | last post by:
I wanna round an value in a javascript Down to nearest hundred. For example: 3234 = 3200 and 3890 = 3800 Always down and to hundred. I have tried Math.floor but that just round down to ten. Is there any way 2 do this?? Regards /Henke
0
1314
by: Gabest | last post by:
I was doing a rasterizer when noticed how slow ceil was. What I found was rather interesting, see my report for more detail: http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=62c7e74e-5f18-4b40-81dc-f6231a45c4a4 Since floor turned out to be that fast, I have even replaced fmod with num - floor(num) in my code. It does not give correct results for negative numbers of course, but to get the coefficient for...
20
2327
by: mikael.liljeroth | last post by:
Why do I get NO as result from this ?? double du = (double)3.1415; du = ceil(du); if(du == (double)4) printf("YES\n"); else printf("NO\n");
7
2452
by: bravesplace | last post by:
Hello, I am using the folling funtion to round a number to a single digit on my form: function round1(num) { return Math.round(num*1)/1 }
110
8585
by: Gregory Pietsch | last post by:
I'm writing a portable implementation of the C standard library for http://www.clc-wiki.net and I was wondering if someone could check the functions in math.h for sanity/portability/whatever. I'm almost halfway through writing the over 200 functions needed to implement C99's version of math.h, and I would like to have some feedback and/or expert advice on my implementations. Sincerely, Gregory Pietsch
9
1741
by: Ken Fine | last post by:
Hi there, I have written a simple function that attempts to set the angle of objects so as to place them in aesthetically appealing ways. The code follows; there is some stupidness in it (e.g. a test for meaningless <=180 as a boolean test). The function is designed to return values that will avoid positioning things a) upside down and b) at "too steep" an angle. I would now like to know how I could write my function so that the...
5
11291
by: matthias s | last post by:
Hi there, I believed that Math.Ceiling is like Math.Round except that it always rounds up to the next but this double d = Math.Ceiling(29/15);
0
8830
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
9324
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8243
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6796
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6074
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4606
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4874
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3313
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2783
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.