Are you aware of the Math#hypot method, which is actually intended for calculating the radius of a circle for polar coordinates. You will probably find it simpler to use than calculating Pythagoras the long way.

You know that the locus of a circle can be defined as (

*r*sinθ,

*r*cosθ)?

You know that incrementing a double by 0.1 is a notorious example of the imprecision of floating‑point arithmetic? You can find the exact value of the double 0.1 here, and you can see it is very slightly greater than 0.1. So it is obvious that your loop will run not more than twenty times. Try it. It will confidently run twenty‑one times

I don't know of Math#hypot, but would it be useful since I'm calculating the y-value, not the hypotenuse?

Also, I have to use Math.pow(x, 2) because the lesson this assignment is for is a lesson on the Math class, and I have been told that if I just do things like x*x, I am "doing the computer's work for it" and I shouldn't be doing that. I will have points deducted if I do that.

The problem is not with that, it's just that it stops early. I was given a screenshot of what it should look like when it's run for radius = 1, and my values matched it.

I just figured out something else. I have this problem between radius values of 1.4 and 4.6, but values less than 1.4 or greater than 4.6 are fine. Even 10 worked fine.

I could use if(radius >= 1.4 && radius <= 4.6) to fix this, but I want to know why this problem is happening and if there is a different way to solve it.

Damien Sky wrote:It is x (the x-coordinate of the point on the circle) that is decreasing by 0.1.

No it isn't, because a coordinate involves

*two*numbers.

My suggestion is that you give us the requirements

**exactly**as they were given to you, because "decreasing by 0.1" could mean almost anything.

Question: Is the idea that you should plot 10

__different__points on the

*same*circle, or 10 similar points on

*different*circles? Because by calling your control field "

`radius`" you're suggesting the latter.

And if it's the first, should they be regularly spaced "around the clock"? If so, a better name for your control variable might be "

`perimeter`".

Inquiring minds want to know...

Winston

"Leadership is nature's way of removing morons from the productive flow" - Dogbert

Articles by Winston can be found here

- 1

By golly, when I run that, it stops before x reaches 1.4, too. Here's the output:

Now, ignore all the helpful tips you've gotten here about the Math class for the moment (and about coordinates being two numbers [Winston, where did you get that idea? ]). As we can see, your problem doesn't depend on circles, computing the other coordinate of a point on a circle, or the Math class at all. Instead,

*something*is making your loop stop early. It's as though x drops below -1.4 one step too soon. Could that really be happening?

Let's push Java for some more information. Your printf only asks for one decimal place. Let's ask for more:

Here's the output:

No surprises there, right? Yet, what Campbell told you is correct:

...incrementing a double by 0.1 is a notorious example of the imprecision of floating‑point arithmetic...

He's right about that, yet our output seems to show no imprecision at all. How could Campbell be right when our output shows perfect precision? Well, let's go the other way and ask printf to show

*no*decimal places:

Here's the output:

Whoa! We sure didn't change how we compute x at each pass through the for loop, yet it only seems to have three different values, each of which gets used more than once! How can that be? The answer is,

*it can't be*. x actually is changing on each pass through the loop. Why doesn't it seem to change on our output? Because printf is rounding it to the number of decimal places we asked for which, in the last case, was zero. Rounded to zero places, a number like "1.1" is printed as "1." So is a number like "1.22," or even "1.20001." With that in mind, let's ask for a lot of decimal places:

You run this one yourself. The output is probably going to surprise you but, once you understand it, you will know the answer to your original question.

Good luck.

"Il y a peu de choses qui me soient impossibles..."

Stevens Miller wrote:Now, ignore all the helpful tips you've gotten here about the Math class for the moment (and about coordinates being two numbers [Winston, where did you get that idea? ]).

Erm, from Maps? Wiki admittedly says that it can be "one or more"; but I can't see how that would work for a circle (which is a 2-D shape) without an agreed centre, radius

*and*"North". And even then, wouldn't it simply be a "bearing" or angle?

I know I'm not a Maths expert, but please tell me where I've gone wrong.

Winston

"Leadership is nature's way of removing morons from the productive flow" - Dogbert

Articles by Winston can be found here

Winston Gutkowski wrote:Stevens Miller wrote:Now, ignore all the helpful tips you've gotten here about the Math class for the moment (and about coordinates being two numbers [Winston, where did you get that idea? ]).

Erm, from Maps? Wiki admittedly says that it can be "one or more"; but I can't see how that would work for a circle (which is a 2-D shape) without an agreed centre, radiusand"North". And even then, wouldn't it simply be a "bearing" or angle?

I know I'm not a Maths expert, but please tell me where I've gone wrong.

Winston

Do you mean "Maps," as in "graphical representations of things like terrain," or are you referring to some Java class called Maps? Anyway, where you went wrong was in saying,

a coordinate involves two numbers.

A coordinate is a single number. A set of them (typically at least two, but one alone is okay) constitute "coordinates." In Damien's case, he is correct to the effect that his loop variable is the x-coordinate in the xy-plane containing his circle. An x-coordinate and a y-coordinate are each a single number. Together, in the xy-plane, they are a pair of coordinates that identify a unique point in the plane. More generally, any number of coordinates can identify a unique point in any n-dimensional space. (There are some boringly complicating extensions to this: for example, a lot of code behind 3-D graphics is written to handle four-coordinate vectors of "homogenous" coordinates, in the form of [x, y, z, w], where the point in 3-space is identified by the three coordinates (x/w, y/w, z/w). Believe it or not, this actually simplifies perspective transformations, since a four-coordinate vector can be multiplied by a 4x4 matrix, which can contain any number of rotations, translations, enlargements, and perspective transforms, all composited upon one another, to put a canonical object into a 3-D scene.)

Damien is trying to compute the y-coordinate of a circle as a function defined on a range of x-coordinate values (actually, since circles aren't functions along any axis in the cartesian plane, he's correctly computing pairs of y-coordinates from each x-coordinate, which, when he solves the problem he's having, may lead him to yet another problem, involving the taking of square roots of negative numbers, but not if he's careful). But, Damien's problem is entirely captured in Campbell's warning about the imprecision of floating-point variables. I'm just trying to help Damien see his problem for what it is, which has nothing to do with circles, powers of two, or what a coordinate is.

"Il y a peu de choses qui me soient impossibles..."

Stevens Miller wrote:A coordinate is a single number.

Aha. My first mistake. I presume then it's called a 'coordinate' because there's a second number involved; maybe the 'origin'?

An x-coordinate and a y-coordinate are each a single number. Together, in the xy-plane, they are a pair of coordinates that identify a unique point in the plane. More generally, any number of coordinates can identify a unique point in any n-dimensional space.

Yeah, that bit I knew (kind of).

There are some boringly complicating extensions to this: for example, a lot of code behind 3-D graphics is written to handle four-coordinate vectors of "homogenous" coordinates, in the form of [x, y, z, w], where the point in 3-space is identified by the three coordinates (x/w, y/w, z/w). Believe it or not, this actually simplifies perspective transformations, since a four-coordinate vector can be multiplied by a 4x4 matrix, which can contain any number of rotations, translations, enlargements, and perspective transforms, all composited upon one another, to put a canonical object into a 3-D scene.

Interesting. I can see I'm going to have to do a lot more reading on this.

Damien is trying to compute the y-coordinate of a circle as a function defined on a range of x-coordinate values (actually, since circles aren't functions along any axis in the cartesian plane, he's correctly computing pairs of y-coordinates from each x-coordinate...

Oh, OK. So if, for sake of argument, x = 1.0 is the "top" of the circle, he wants to know the y values as he goes linearly down the x axis in steps of 0.1 to 0, which can then be mirrored for the lower half of the semicircle.

*Now*I get it (I think). Tell me if I'm wrong.

Winston

"Leadership is nature's way of removing morons from the productive flow" - Dogbert

Articles by Winston can be found here

Damien Sky wrote:I created a double "increment" and changed the code to this:

I think you're concentrating a bit too much on the code at the moment, and not on WHAT you need to do. Sorry for steering you wrong on the 'coordinates', but here I

*do*know what I'm taking about (promise ).

1. Without going into the internals of floating-point numbers (eg,

`double`) in detail, there is only

*one*class of value that you can be sure will be held

__exactly__:

*whole numbers*(and there are limits for those too).

*Most*other values - and certainly most that are returned by functions - will be

*approximations*.

One such value in particular is 0.1 (which is very likely why it was given to you for this problem). A

`double`simply cannot hold 0.1 as an exact value - and for this reason, they tend to make very poor control values for loops. On the other hand:

`int one = 1;`

double x = one / 10.0;(Note: the '.0'

double x = one / 10.0;

__is__important; I'll leave you to discover why)

will set

`x`to the

*closest*value to 0.1 it's possible for a

`double`to hold. Now, how do you think you might be able to use

*that*knowledge to re-tool your loop?

2. StopCoding (←click).

You plainly know

*roughly*what you want to do, but you haven't thought it through completely; which is why you're now having to resort to 'tweaking' to get it right. Write down exactly what you want to do,

*in detail*and

**in English**before you write any Java code. For one thing, it helps

*you*understand the problem better; and for another, it makes the whole business of coding very much easier.

It's a pain when you're just dying to see results but believe me,

*it works*. It's also a very good habit to get into for later on because - trust me - these problems are only going to get harder.

HIH. And if you're interested in more information about floating point values, bookmark this page.

Winston

Articles by Winston can be found here

OP a clue on how to avoid these floating point inaccuracies.

Winston is right, use integer arithmatic. Suppose you have some segment [a, b], for which you want to

calculate some evenly spaced sequence [x(0) = a, x(1), x(2), .., x(n) = b].

Then the formula x(k) = a * (n - k) / n + b * k / n does miracles.

For instance (I've choosen n such that the increment = 0.1):

Edited: put the square root in

- 1

"Il y a peu de choses qui me soient impossibles..."

Winston Gutkowski wrote:Oh, OK. So if, for sake of argument, x = 1.0 is the "top" of the circle, he wants to know the y values as he goes linearly down the x axis in steps of 0.1 to 0, which can then be mirrored for the lower half of the semicircle.

NowI get it (I think). Tell me if I'm wrong.

Winston

Pretty close. He wants to go from 1.0 to -1.0 (the "top" of the circle is at x=0.0). My whole reason for being a pest about coordinates and the Math class is simply that his problem has nothing do with circles or any related complicating topics. He's just coping, as many of us have, with the fact that subtracting 0.1 from 1.0, twenty times, does

*not*yield -1.0 as his final result. I just wanted him to focus on that, and that alone, until he came to grips with the rather mind-bending fact that computers are crap at doing sums. (Well, it was mind-bending to me, when I had to come to grips with it.)

"Il y a peu de choses qui me soient impossibles..."

Piet Souris wrote:In principle I agree. However, seeing that after your long reply, the discussion went

from homogenous coordinates to stop coding, I thought that a shortcut could

speed up things. Well, I wonder what OP has to say.

Hey, my words are golden. You should be grateful when I'm prolix .

Actually, Winston's oft-given advice to stop coding (I tend to word that as, "keep your hands where I can see them and step away from the mouse"), is applicable here. Damien needs to understand the nature of floating point numbers to know why his loop was working the way it was. Heh, when I first coped with this (which was in 1975), knowing how floating-point numbers were actually encoded was a kind of rite of passage for programmers. Today, Java's philosophy, that native types must be opaque, seems somewhat in conflict with knowing why integer types are (within their ranges) always exact, but floating types cannot be similarly trusted. My beloved "Core Java" introduces floating-point numbers by describing

`float`s and

`double`s in terms of how many "signficant digits" of precision they have. It then goes on to warn against using them in "financial" calculations, because of round-off (even explaining that neither a float nor a double can exactly represent the value 1/10). But, taken as a whole, a beginner could end up thinking, "Well, I'm computing the coordinates of points on a circle, not running a bank, so this isn't a financial calculation, and I've got a circle of radius 1.0, with steps of only 0.1, so six significant digits will certainly be enough for me." Indeed, if Java were to use binary-encoded decimal (something I would

*not*support, of course) as the internal format of its floats, Damien's first program would have worked fine, and floats would be just as opaque as they are now. It's because they use the internal format that they do, that he is having a problem, and that opacity may, however unintentionally, be part of the reason.

"Il y a peu de choses qui me soient impossibles..."

Hahahahahahaha! Do you have to hold a Colt .45 as you say that?Stevens Miller wrote: . . . "keep your hands where I can see them and step away from the mouse" . . .

Or maybe that two's complement arithmetic and IEEE 754 numbers were well‑known before Java was developed and they took it for granted people knew how binary arithmetic works?Today, Java's philosophy, that native types must be opaque, seems somewhat in conflict with knowing why integer types are (within their ranges) always exact, but floating types cannot be similarly trusted. . . .

Campbell Ritchie wrote:Hahahahahahaha! Do you have to hold a Colt .45 as you say that?Stevens Miller wrote: . . . "keep your hands where I can see them and step away from the mouse" . . .

Heavens, no! My weapon of choice is far more persuasive:

Or maybe that two's complement arithmetic and IEEE 754 numbers were well‑known before Java was developed and they took it for granted people knew how binary arithmetic works?Today, Java's philosophy, that native types must be opaque, seems somewhat in conflict with knowing why integer types are (within their ranges) always exact, but floating types cannot be similarly trusted. . . .

Man, if the people you hang with know about such things, I'd like to spend more time with them myself. For a newcomer to coding, I think that might be somewhat abstruse subject matter.

To pursue that a bit, though: is it safe to assume that opaque types will never change internally? I am guessing the language spec calls for a format, but I really don't know and, even if it does, does it say the format will never change? I was kind of embarrassed, when I started learning Java, to realize I didn't even know what "opaque" meant, in the context of a programming language. As I understand it now, however, the virtue of opacity is that I am neither supposed to care

*nor know*how a type is structured internally, so I neither have to accommodate that structure, nor can I do anything that would rely on that structure never being changed in the future.

Good example of me still having a lot to learn. If I've got any of this wrong, please help me out.

"Il y a peu de choses qui me soient impossibles..."

We used to teach binary integer arithmetic (in 8 bits) and floating point arithmetic (IEEE 754 in 32 bits) to our freshers, so they should have some idea how the numbers are represented long before getting their BSc.

Campbell Ritchie wrote:You need to know about the structure of primitives so you know about overflow (integers) and underflow (floating‑point only). Actually floating‑point numbers can overflow too, in which case you get ±∞.

That raises a very important pedagogical point: teaching someone to program before they know the limitations of the primitive types they will be working with is kind of like teaching someone how to build a house before they know how much weight a foundation can bear. Damien's problem should have been the actual subject matter of his assignment. Or, more precisely, he should have been given an assignment that would reveal to him, and help me learn to cope with, the limitations of floating-point numbers. (I suppose he might have been given such an assignment, and we just don't know about it, but that appears unlikely, to me.)

I never got a bachelor's in CS (mine's in physics). My master's program must have assumed we already knew this stuff, because it never came up directly. In my own case, I learned about two's-complement and various schemes for representing floats by reading Byte and working with a textbook the Sperry-Univac company used for an in-house course on computers. (My dad got that for me from a friend, when I was 15. I read the whole thing and they even let me take the final exam. I still have the certificate that says I passed, somewhere. The bums declined to give me a summer job, regardless, but I see that as their loss.)

But, yeah, this isn't something you can ignore if you're going to write computer programs. As dry as it may be to students hoping to write Xbox games, it really does need to be part of their primary education.

"Il y a peu de choses qui me soient impossibles..."

*something*about how digital computers store floating-point numbers, it can be virtually impossible to understand.

If he were computing points on a circle by entering an x and obtaining a y, the fact that floats/doubles are imprecise would, as you say, impose some inaccuracy upon his result. But his real problem is that he is trying to iterate a function over evenly space values in its range, and his approach is failing for a rather subtle reason. It doesn't matter that he's computing points on a circle (or even that he's computing anything based on his x value at all). What matters is that he wants his computer to generate a set of values (specifically, [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, 0, -0.1, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7, -0.8, -0.9, -1.0]), and that, although his code is arithmetically correct, it doesn't work. The reason it doesn't work has nothing to do with his math (which is fine). It doesn't work because Java literally cannot store the number 0.1 in a float (or a double). It stores a nearby value that, for many purposes, is good enough. But, when used to increment or decrement a loop-control variable, it's not that it isn't sufficiently accurate: it's that it doesn't work at all. (Put another way, he wants 21 values from his loop, and he's only getting 20, because floats and doubles can't do exact math. That's not an inaccuracy; it's a outright failure to meet his objective.)

(Oh actually, his program seems to work over the range [1, -1]. It breaks when he tries to cover the range [1.3, -1.3], so he is really trying to generate 27 values when he's only getting 26. Same point applies, though.)

"Il y a peu de choses qui me soient impossibles..."

You have opened up an interesting discussion here. When I started programming Java® I was told never to use doubles or floats in loops because of such imprecision.

You can get tenths like this:-…but if you enter a negative number your loop will never start.

Have you thought of this formula for the

*y*coordinates?

*θ*= r

*cos*⁻¹x

*y*= r

*sin*θ

There are methods in the Math class for sin() and cos⁻¹ (I think acos()).

Stevens Miller wrote: (...)

The difference between you and me (in this respect) is that you consider this issue

far more fundamental than I do. And I respect your attempts to make the

inaccuracy that comes with floating points, clear to Damien. I can't give you a

cow for that, but accept my virtual one.

I only hope we didn't scare Damien off!

Greetz,

Piet

Piet Souris wrote:OP is having a minor problem with a boundary, and so he's facing some inaccuracy

that comes with floating points. That's all. Why OP should stop coding and follow a

course in IEEE 754: it seems a bit heavy to me.

Popped back to this thread after a while. And I'm going to try and answer that (especially since I'm the one that wrote the StopCoding page ).

It's the same as the reason that I'm very grateful to have someone like you around when I make a mathematical fallacy. I'm NOT a mathematician, but I do at least know that it's possible for me to make dangerous assumptions based on what I

*think*to be true. And I need a Piet to tell me when I'm wrong.

If Damien doesn't understand

*why*floating-point values have these inbuilt "gotchas" (and I'm not sure that he needs to read the entire IEEE-754 spec; Goldberg explains it pretty succinctly) he runs the risk of simply learning this example by rote, and/or not recognising it when it comes up in other guises (eg, currency calculations).

StopCoding is along the same lines, except that it's

*procedural*advice.

When you start out programming, the first thing you do is CODE; and if you're smart, you can actually get quite a way by simply coding, because you can store an entire algorithm in your head. But there comes a point at which that process breaks down - and if you've never learned any other way of doing things, it usually breaks down catastrophically.

It also manifests itself

*before then*in an increasing frustration at "why things don't work". The poster feels that "it ought to be simple", but it

__isn't__; and they find they're making basic mistakes. And the reason (at least in my opinion) is that they've only ever been used to dealing with a problem

*as a whole*, and as problems increase in complexity they get overwhelmed by the scope - and hence they get early lessons in debugging and (even worse) "tweaking".

I think it's also sound psychology. How many times have you been told, when you're desperately trying to remember something that's just maddeningly out of reach:

Forget about it. You'll remember when you're thinking about something else.

Well, the same is true of logic. And stopping coding - especially if you remember the other part of that advice:

*turn your computer OFF*- forces you into a different mindset. You can't code, so you're forced to

*think*. Most pros I know spend very little time coding, and actually consider it the most boring part of their job, because all it involves is translating what they

*already know*into Java (or whatever).

I should add that it's BTDTGTTS advice.

My TGIF 2¢-worth.

Winston

PS: Happy Halloween everybody.

Articles by Winston can be found here

Stevens Miller wrote:Winston's oft-given advice to stop coding (I tend to word that as, "keep your hands where I can see them and step away from the mouse")

Is it just a coincidence or is it a disturbing trend that more programmers do their work with a mouse these days? I for one still use a keyboard to program. In fact, I'm trying to free myself from having to use a mouse.

*Practice only makes habit, only perfect practice makes perfect.
Practice mindfully by doing the right things and doing things right.*— Junilu

[How to Ask Questions] [How to Answer Questions]

Junilu Lacar wrote:In fact, I'm trying to free myself from having to use a mouse.

Get a copy of Solaris (if you still can) and turn the desktop off. Still the best Unix AFAIC - although I'm told that you can do similar things with Debian.

Winston

Articles by Winston can be found here