This week's book giveaway is in the Kotlin forum.We're giving away four copies of Kotlin in Action and have Dmitry Jemerov & Svetlana Isakova on-line!See this thread for details.
Win a copy of Kotlin in Action this week in the Kotlin forum!
programming forums Java Java JSRs Mobile Certification Databases Caching Books Engineering Languages Frameworks Products This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
Sheriffs:
Saloon Keepers:
Bartenders:

# Confusion over using doubles for positioning objects and testing equality

nick woodward
Ranch Hand
Posts: 372
11
Hey all!

I've been noticing some of my programs have been a little buggy recently, and think it's down to confusion over doubles and positioning. Was hoping someone could help clear this up a bit!

Lets say I have a label called banner that I want to scroll across the screen. Now I need to know the label's width in order to position it, but the width depends on the amount of text, so i use this code:

Which forces me into using a double if I want to be accurate.

But the problem is that I'm trying to use a condition that compares the label's horizontal position (currentX) to the left edge of the screen (LEFT_EDGE), minus the width of the label (bannerWidth). In other words when the label is off the screen, it should go back to its starting position.

I assume that means that any variables I use to track the label's position (in this case currentX), or constants that I use to check equality (LEFT_EDGE), have to be doubles as well?

My difficulty is that I iterate currentX. But currentX--; won't work because doubles don't iterate as I'd expect.

So casting becomes an option..... but if I cast to an integer I effectively lose width on the label. And that is magnified each loop, resulting in the label's starting position moving further and further to the left.

Can anyone help clear up my confusion at all? I hope I've described the problem adequately enough. Let me know otherwise!

nick.

Rob Camick
Ranch Hand
Posts: 2800
15
Not sure why you care about "doubles". All sizes in Swing components are "int" based, so all calculations should be "int" based. That is you can only scroll 1 pixel at a time.

If you want to know the size of a component you should be using:

If you want you can check out Marquee Panel, which is a panel that scrolls components and has a few fancy features.

nick woodward
Ranch Hand
Posts: 372
11
Rob Camick wrote:Not sure why you care about "doubles". All sizes in Swing components are "int" based, so all calculations should be "int" based. That is you can only scroll 1 pixel at a time.

If you want to know the size of a component you should be using:

If you want you can check out Marquee Panel, which is a panel that scrolls components and has a few fancy features.

i assumed that banner.move(1,0); was one pixel at a time because it was implicitly cast to banner.move(1.0,0).

but maybe not.

i'll have a look at banner.getPreferredSize().width, but realistically i have no idea what that means.

its a method called on banner, but how is width after 'getPreferredSize', and how does that differ from getWidth()?

i'm sure i'll have a look tomorrow, but those are my initial thoughts!

nick woodward
Ranch Hand
Posts: 372
11
i guess i'm confused because this is one of the examples in the book i'm using:

why is this example using doubles for dx and dy, and SQUARE_SIZE?

what happens if i'm using calculations to position objects and the result is say 2.5? does the truncation (or casting to an int if that is what happens) not matter?

*edit: ^ i've pretty much just answered my own question by removing all doubles in my program, it works better.

but the book is continuing to use doubles to position graphical objects.......

Campbell Ritchie
Marshal
Posts: 55698
163
Which book?

Piet Souris
Rancher
Posts: 1979
67
It is not so uncommon to use doubles for positioning, even when a Graphics is
pixel based.

What's wrong with Nick's example? Something has to move a certain distance
in a certain number of steps. Using a double in this case is natural, to keep
the motion smooth.

In my chess program, I use a similar technique. Say I have to move a piece
over 240 pixels, and I want to do that in one second, where the timer fires
50 times a second. Then the distance per update = 240 / 50 = 4.8 pixels
at a time. So, I get: currentX += distance_per_update, and only when I paint
the icon, I round the coordinates.

Greetz,
Piet

nick woodward
Ranch Hand
Posts: 372
11
Piet Souris wrote:It is not so uncommon to use doubles for positioning, even when a Graphics is
pixel based.

What's wrong with Nick's example? Something has to move a certain distance
in a certain number of steps. Using a double in this case is natural, to keep
the motion smooth.

In my chess program, I use a similar technique. Say I have to move a piece
over 240 pixels, and I want to do that in one second, where the timer fires
50 times a second. Then the distance per update = 240 / 50 = 4.8 pixels
at a time. So, I get: currentX += distance_per_update, and only when I paint
the icon, I round the coordinates.

Greetz,
Piet

but say i had an object(GLabel) positioned at 100,100 (just off the right of the window), and i wanted it to move one pixel per cycle to the left until it met the condition of being just off the left of the screen (LEFT_EDGE - label.getWidth).

if the position of an object was a double, how would i track its movement in a loop? i can't iterate it (as far as i know), i also can't seem to make it move back to its original position (label.getWidth*2+this.getWidth) once the condition (labelX == LEFT_EDGE-label.getWidth) is satisfied without getting funky results after the 2nd or 3rd loop across the screen (which tells me that the calculations for the movement back to the right of the screen are out by a fraction - which i put down to using the double).

it isn't overly important now, but i would be interested to know where i went wrong. think the book is a little misleading tbh, and even if it is ok to do - taking the advice from here and just using ints worked wonders!

Piet Souris
Rancher
Posts: 1979
67
hi Nick,

it may soud a bit clichÃ©, but:

1) know what it is you want to do
2) after that, know how to implement it

First of all, and I think I will not be telling you anything you haven't heard before:
floating point arithmatic is inaccurate, meaning it is dangerous to compare for equality.
Say, you have two doubles, d1 and d2, then 'if (d1 == d2) ...' is asking for trouble.

Look at the following short program.

Compare that to:
So, when working with doubles, do not use equality, but use somethin like 'is close enough'.
See the next code:

The loop now finishes nicely, it stops when i is close enough to 1.0.

Whether or not to use doubles, depends on what it is that you want to do.
If you want an object to move a fixed number of pixels, then use integers.
Then you have all the accuracy you need. You have such a situation when you
let your square wander around, bouncing off walls, Integers are perfect for this.

But there are other situations thinkable. I already gave an example of what I
do in my chess program, when I animate a chess move.

If I look at your last example, I see the following code:

This is a comparable situation. You want to move your square from right to left,
but you must do that in N_STEPS moves, no more, no less. And then doubles come into
play.

For instance, say you need to move 240 pixels to the right, from 0 to 240, in 50 moves.
Now, if you were to move 4 pixels per step, then after 50 steps, you end
up having moved only 200 pixels. If you use 5 pixels each time, you end up with
having moved 250 pixels. So, the alternative is to use steps of 240 / 50 = 4.8 pixels.

"But in a Graphics object you must use integer coordinates!"

Indeed, but that is only when we need to draw something!
If we follow the coordinates in my example, we get:

after turn 1: x = 4.8 => when drawing, use 5
after turn 2: x = 9.6 => when drawing, use 10
after turn 3: x = 14.4 => when drawing, use 14
after turn 4: x = 19.2 => when drawing, use 19

and so on.

Now, when do you stop using this animation?
In my second example, using integers only, you can safely check for equality.
It boils down to exact determination of your 'borders'.

If you are using doubles, then you can do two things:

1) use what you did in the routine of your book. You know you must iterate N_STEPS
times, so that's what is done there.

2) determine your 'border', and use the 'isGoodEnough' method of my third example.

And as always: practise and experiment as much as you can! You will learn most of that.
And if in doubt, go back in your book and start reading again. Chances are that you will
understand much better what the author is doing.

Greetz,
Piet