Problem in the Perl script

R

Rashmi Madhukara

Hello All,

For some reason, I am not able to reason out why this piece of
program is not working.

my $k = 1.0;
my $num = 3;


for($k = 2.0; $k <= 10.0;)
{
$k = $k + 0.1;
if($k == $num)
{
print "True\n";
}
}

In the above program for some reason, it doesn't print True.

Thanks in advance
R
 
S

stu42j

Hello All,

For some reason, I am not able to reason out why this piece of
program is not working.

my $k = 1.0;
my $num = 3;

for($k = 2.0; $k <= 10.0;)
{
$k = $k + 0.1;
if($k == $num)
{
print "True\n";
}

}

In the above program for some reason, it doesn't print True.

Thanks in advance
R

See: http://perldoc.perl.org/perlfaq4.html#Data:-Numbers

You'll probably want to multiply everything by 10 to keep them
integers.
 
J

Jürgen Exner

Rashmi said:
Hello All,

For some reason, I am not able to reason out why this piece of
program is not working.

my $k = 1.0;
my $num = 3;


for($k = 2.0; $k <= 10.0;)
{
$k = $k + 0.1;
if($k == $num)
{
print "True\n";
}
}

In the above program for some reason, it doesn't print True.

Trivial. You simply missed the first commandment of Computer Numerics.

"Thou shalt not use equal on floating point numbers"

For a 5 second overview about why that is a bad idea see the FAQ 'perldoc -q
999'. For more in-depth explanation see any basic introductory book into
computer numerics, chapter 1.

jue
 
X

Xiong Changnian

In general, you don't want to test floating-point numbers for equality.
It will almost always bring you to grief. Some would put it even more
strongly.

Perl has no fixed-point numeric format. There are only integers and
floats. If a variable has *ever* stored a non-integer value, it will
want to use floating-point format.

I like to think of integers as digital values, floats as analog values.
It's possible to say truthfully, for example:

"I have some marbles in this cup. I have some apples in this basket. The
number of marbles is exactly equal to the number of apples."

However, this statement is fraught with peril:

"I have a red stick and a blue car. The length of the stick is exactly
equal to the length of the car."

There is no way to verify this, because you cannot measure either stick
or car with infinite precision.

There are ideal situations in which it is true that two analog
quantities are equal. For instance, in the standard construction of an
equilateral triangle with compass and straightedge, the length of each
side is an analog quantity that we'd probably represent with a float. By
definition, all these lengths are exactly equal. If we were to calculate
these lengths using floating-point variables, they might not test as
equal, though.

But such situations only occur in ideal space. Real-world analog
quantities, represented by real numbers, can never be determined to be
exactly equal. All we can ever say is that they are equal to the limits
of our measurement method.

my $truth;
my $num = 0.000003;
my $lim = 0.0003;

$num = $num * 100;
$truth = ($num == $lim) ? 'true' : 'false';
print ("$num, $lim, $truth \n");

.... outputs:

0.0003, 0.0003, false (at least on my machine)

Testing for float equality is especially risky because floats are *not*
infinite-precision real numbers. You might get "lucky" with a test case
or two and think your code works. Developing the code above, I
experimented with some "simpler" examples which tested 'true'.

Testing for float equality is a sign that you need to rethink what you
are doing. Why do you want to do this? Get out of the code for a moment
and look at the real-world situation. What analog variables could you
want to be exactly equal?


Here, I want to know when I've cooked my breakfast long enough:

sub cook {
# cook eggs for six seconds
return 0.1;
};

my $time = 0;
my $done = 3; # minutes

do {
$time += cook();
} until $time == $done;

print ("$time, $done \n");

This loop will never exit until I run screaming into a kitchen full of
smoke. However, if I change the test to:

until $time >= $done;

.... the program will exit happily with output:

3, 3

Eggs are never *exactly* done but there is a time when they are done
enough. The reason that perl prints 3 for $time is that an ugly detail
is being hidden from you -- it is *not* exactly 3.

In other cases, you might be better to use an explicit, integer
iterator:

for (my $i = 0, $i == $max, $i++) {
$time += cook();
};

Of course, you have to choose $max wisely.

Another approach is to test the eggs themselves for doneness:

sub cook {
# cook eggs for six seconds
return 0.1;
};

sub done {
# return 1 if eggs look done, 0 otherwise
};

do {
cook();
} until done();

print ("Done! \n");

You have to decide what a done egg looks like. This works well for fried
eggs, not well for boiled eggs.


A different need might involve biometric data. Your secret agent steps
on a scale before being granted access to the men's room:

%::metrics = (
SMITH => 143.24,
JONES => 175.02,
);

sub pass_agent {
print (">agent passed< \n");
};

sub incinerate_agent {
print (">agent incinerated< \n");
};

sub weigh {
# return weight from scale device
143.2400001;
};

sub verify_agent {
my $agent = shift;
my $weight = weigh();
if ($weight == $::metrics{$agent}) {
pass_agent();
}
else {
incinerate_agent();
};
};

verify_agent ('SMITH');

Agent Smith will always be incinerated because there is no way for him
to weigh *exactly* as much as he did back when you created the
%::metrics "database". (Yes, that should be a tied hash. Okay?) Every
time Smith breathes, he gains or loses some trivial amount of weight.

What if we declare some very small value by which Smith's weight is
allowed to vary?

$::epsilon = 0.01;

We change our test to:

if ( abs ( $weight - $::metrics{$agent} ) < $::epsilon ) {...

Smith will still want to watch that extra donut but at least he has a
chance of making it to the men's room.


In still another case, you're not using an analog value at all but it
appears to be a fraction or decimal. For example, you are turning a
rotary switch through a full circle. There are eight detents in the
switch, so you say:

my $click = 1/8; # one-eighth of a turn
my $turn = 1;

Later, you accumulate clicks until you reckon you've made a full turn.
This may fail but a slightly different approach succeeds:

my $click = 1;
my $turn = 8; # eight clicks

* * *

I suggest that if you think it over, you'll see that you never *want* to
test floats for equality. It's not a matter of language; it's a matter
of your intent.

To tell the truth, I rarely test an *integer* for == if I've done any
sort of arithmetic operations on it other than ++. If I'm exiting a
loop, I test (as above) for >=. This is doubtless excessively paranoid
but I'd rather exit with the wrong number of iterations than not exit at
all.
 
P

Peter J. Holzer

In general, you don't want to test floating-point numbers for equality.
It will almost always bring you to grief. Some would put it even more
strongly.

Perl has no fixed-point numeric format. There are only integers and
floats. If a variable has *ever* stored a non-integer value, it will
want to use floating-point format.

I like to think of integers as digital values, floats as analog values.

While that will prevent you from making one set errors, it will lead you
to another set.

Floating point values are not analog. They are discrete, just like
integers. There is a finite set of different floating point numbers (for
a given implementation), each of them has an exact value, and for each
of them (except the smallest and the largest) there is a smaller and a
larger neighbour, and there are no other FP numbers between a number and
its neighbours (just like there are no other integers between say 54 and
55).
In still another case, you're not using an analog value at all but it
appears to be a fraction or decimal. For example, you are turning a
rotary switch through a full circle. There are eight detents in the
switch, so you say:

my $click = 1/8; # one-eighth of a turn
my $turn = 1;

Later, you accumulate clicks until you reckon you've made a full turn.
This may fail but a slightly different approach succeeds:

Bad example. Given a binary floating point representation, this cannot
fail, because 1/8 is representable exactly.

hp
 
X

Xiong Changnian

Floating point values are not analog...

Yep. You're right. I said, I like to *think* of them that way. I don't
even think of them that way all the time. I just like to, when I can.
Often it's a useful approximation. Sometimes it's not. There is no
obvious, blatant, and exact analogy to floats in the real world, so when
I can, I settle for obvious, blatant, and inexact.

Bad example. Given a binary floating point representation, this cannot
fail, because 1/8 is representable exactly.

Hey, you're right! But only if I abandon abstraction to the point of
recognizing how floats are represented. I don't like to do that. I
prefer to assume (my) ignorance. If I want to be informed, I'll
assemble. I'm learning Perl so I can ignore all that stuff.

You win. Okay?
 
J

Jürgen Exner

Michele said:
Nope, on a computer all values are discrete, period.

True. But Xiong is talking about mental models "like to think ... as". And
humans have an amazing ability to adjust the current mental model to
whatever is most useful at the time.
Example: Hopefully 99% of us agree that the earth is not flat. Still when
driving around town or laying out a route on an auto map we do not bother
about spherical trigonometrie but simply pretent that our town is flat.
Experience has shown us that for this specific application (driving a car)
we can safely ignore the much more complex model of the earth being a geoid.

Same with floats as analog values. Of course that's not what they are and
Xiong realizes that. But using that mental model helps Xiong to avoid the
common pitfall of comparing two values for equality. That doesn't imply, he
believes in the flat earth. I think it is a great idea.

jue
 
T

Tony Mc

In the real world... first or later you have to cope with the
philosophy of physics and mathematics. Do reals really exist? :) In
my reply to your post I wanted to include a quote from a famous
mathematician (although I can't remember exactly which one, although I
can make a few guesses) to the effect of something along the lines of
"God created integers, all else is work of men": actually I had read
it as an epigraph in a book I don't have available at the moment and
it was in German. I don't know German, but it was quite
understandable, something along the lines of "Gott *** die zahlen, alt
else ist menshenwerke." (Apologies to German fellows out there.) I
wanted to locate it to report it appropriately, but Google didn't
help...

Leopold Kronecker, I think.

Tony
 
P

Peter J. Holzer

Yep, I think so too. Do you have the full, actual, precise quote? I
tried with some IMHO reasonble search like
<http://www.google.com/search?q=kroenecker+zahlen+menshenwerke+quote>,

Surprisingly, Google does suggest the correct spelling:

Meinten Sie: kronecker zahlen menschenwerke quote

but still finds nothing. After removing "quote" from the search string
it does find two instances of the quote. ("Menschenwerk" finds a lot
more than "Menschenwerke", as the latter is wrong in modern German (and
may be a misquote by non-German speakers)

hp
 
X

Xiong Changnian

Michele Dondi said:
Do reals really exist?

Probably not; the evidence seems to be leaning the other way. It's very
hard to say and perhaps will always lie, with most cosmology, in the
realm of faith. I certainly prefer discrete models.

This is among the earliest philosophical questions to be raised.
Democritus and Leucippus advocated a theory of indivisible /atoma/; the
discovery of subatomic particles has done nothing to upset this
position. Plato and Aristotle argued for infinite divisibility of the
universe: a continuum. Well, Aristotle also argued for heavier objects
falling faster.

My mother was a combinatorialist, so blame her if you like for my atomic
orientation. I'd venture that programmers in general side with atomists;
our tools are digital so we tend to believe in quanta. Perhaps if analog
computers had turned out to be cheap, compact, and reliable, we would
lean to a continuum.

The general public today seems to stand in the camp of the atomists. My
students often demand to know the "real", true value of pi; they are
unsatisfied with all explanations. It is said that the irrationality of
the diagonal of a unit square was a scandal and a guarded secret of the
Pythagoreans.

When I was young, I was such a stubborn atomist that I remarked to an
engineer my senior that I had no interest in electronics outside of
digital logic. Our project was an early CCD camera -- which, despite
such things being called "digital cameras" today, demand quite a bit of
analog TLC. I swaggered with a belly full of boolean truth. The senior
man said, "You'd better branch out. It's an analog world." It took me
years to believe him but I did eventually delve into transistor and
op-amp theory. Now, I'm one of a dwindling number of San Jose residents
who are willing to do small analog projects for clients.

I say all this to show that I see both sides of the issue. I think any
given problem may be best approached with a flexible blend of views. I
don't believe that any fixed rule or orientation makes for the best
solution.

We've all heard the story of the IBM interview question: "Why are
manhole covers round?" I first heard it from my father, who failed to
land the job. When I ask it -- as I often do -- of my students, I'm
often surprised by how many just can't wrap their brains around the
basic requirement: to come up with a large number of inventive, perhaps
conflicting explanations. They fixate on the need -- expressly
disclaimed -- to discover the one "right" answer.
 
U

Uri Guttman

XC> Perl has no fixed-point numeric format. There are only integers and
XC> floats. If a variable has *ever* stored a non-integer value, it will
XC> want to use floating-point format.

i wouldn't use the word format there. perl uses a machine integer or
float inside an sv as appropriate and will convert from one to the other
on the fly.

look at perldoc perlguts for more. and Scalar::Utils has subs that can
tell you what type of data is in an SV.

uri
 
X

Xiong Changnian

We've all heard the story of the IBM interview question: "Why are
manhole covers round?"

I hadn't. I didn't even know what "manhole" meant. Of course I do know
what a manhole is. I just didn't know the English word....[/QUOTE]

Philip Roth writes of his struggle with his parents' native language
(Yiddish) in /Portnoy's Complaint/:

I was already the darling of the first grade, and in every schoolroom
competition, expected to win hands down, when I was asked by the teacher
one day to identify a picture of what I knew perfectly well my mother
referred to as a "spatula." But for the life of me I could not think of
the word in English. Stammering and flushing, I sank defeated into my
seat, not nearly so stunned as my teacher but badly shaken up just the
same...in a state resembling torment -- in this particular instance over
something as monumental as a kitchen utensil.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top