From: solar on
Hi,

There seems to be a bug in the way numbers are compared in Tcl.
Consider the below script for calculating Pythagorean triplets.
For hypotenuse upto a value of 100, there should have been 63
unique triplets.

On Windows XP the script detects only 62. The script doesn't detect
the case where c=99, b=20 ==> a=101.

However running the same script under Tcl 8.4.1 in Cygwin detects
63 triplets.

I don't have a Linux machine at hand to test it there.

Following is the script and relevant output. Could anyone shed some
light
on the cause of this. Maybe it has something to do with how the
numbers
are represented internally?

Running the script for N>100 shows up many more such missed values.
An equivalent program in C runs correctly on the same machine. C code
was compiled using both gcc and VC++6.0.


#########################################################################
# a^2 = b^2 + c^2
proc pythag {MAX} {
set i 0
for {set c 2} {$c <= $MAX} {incr c} {
for {set b 1} {$b < $c} {incr b} {
set a [expr hypot($c, $b)] ;# Calc. Hypot

if { ($c == 99) && ($b == 20)} { ;# <<<<<<<<
puts ">> [expr round($a)] == $a"
}

if {[expr round($a)] == $a} {
puts "$a : $b : $c"
incr i
}
}
}
return $i
}

if {$argc == 1} {
set MAX [lindex $argv 0]
} else {
puts stderr "Usage: tclsh $argv0 N"
exit
}

puts [pythag $MAX]

############# OUTPUT ################
Tcl 8.4.1 (Cygwin)
------------------------
5.0 : 3 : 4
10.0 : 6 : 8
<snip>
104.0 : 40 : 96
120.0 : 72 : 96
>> 101 == 101.0
101.0 : 20 : 99
125.0 : 75 : 100
63

Tcl 8.4.18 (Activestate Dist.)
---------------------
5.0 : 3 : 4
10.0 : 6 : 8
<snip>
104.0 : 40 : 96
120.0 : 72 : 96
>> 101 == 101.0
125.0 : 75 : 100
62

Tcl 8.5.2 (Activestate Dist.)
----------------------
5.0 : 3 : 4
10.0 : 6 : 8
<snip>
104.0 : 40 : 96
120.0 : 72 : 96
>> 101 == 100.99999999999999
125.0 : 75 : 100
62
###########################################


TIA
--
From: Larry W. Virden on
On Sep 4, 12:58 pm, solar <solaradmin2...(a)gmail.com> wrote:

>> 101 == 100.99999999999999

From what I can tell, looking at tcl/generic/tclBasic.c and
tclExecute.c, along with tclWinPort.h , Tcl is calling what appears to
be the underlying C library hypot function directly. At least on Unix,
that function is defined to take 2 type double arguments and returns a
double return code.

Here's the peculiar thing. I modified your example to ensure that the
2 arguments to hypot were truncated to be an integer. So the values
passed to hypot should in my case anyways be exactly 20 and 99. The
underlying function, it would seem to me, should be calculating the
result as the square root of 10201. One would think that, even with
the fuzziness of floating point, that the answer to that question
would be 101. Apparently not, however.

http://wiki.tcl.tk/879 is one of I suspect several wiki pages that
discusses the dilemma of dealing with real numbers.



From: Bruce on
Larry W. Virden wrote:
> On Sep 4, 12:58 pm, solar <solaradmin2...(a)gmail.com> wrote:
>
>>> 101 == 100.99999999999999
>
> From what I can tell, looking at tcl/generic/tclBasic.c and
> tclExecute.c, along with tclWinPort.h , Tcl is calling what appears to
> be the underlying C library hypot function directly. At least on Unix,
> that function is defined to take 2 type double arguments and returns a
> double return code.
>
> Here's the peculiar thing. I modified your example to ensure that the
> 2 arguments to hypot were truncated to be an integer. So the values
> passed to hypot should in my case anyways be exactly 20 and 99. The
> underlying function, it would seem to me, should be calculating the
> result as the square root of 10201.

doesn't matter if the inputs are integers - the result is a double

> One would think that, even with
> the fuzziness of floating point, that the answer to that question
> would be 101. Apparently not, however.

why do you think 101 would have an exact representation in binary?

>
> http://wiki.tcl.tk/879 is one of I suspect several wiki pages that
> discusses the dilemma of dealing with real numbers.
>
>
>

yes the may be variances in behavior accross versions of tcl and various
OS's but the only "bug" I see is in the code of the script itself that
is doing an exact comparison of floating point numbers.

a better check would be to get the rounded result - cast to integer
and then square that integer and compare it to the sum of squares of
the input. (since you end up needing the sum of squares anyway, you
could calc that then just use sqrt (then round, then cast, then square)
instead of using hypot.

or you could just change you comparison to use a suitable epsilon.

Bruce
From: Kevin Kenny on
solar wrote:
> Hi,
>
> There seems to be a bug in the way numbers are compared in Tcl.
> Consider the below script for calculating Pythagorean triplets.
> For hypotenuse upto a value of 100, there should have been 63
> unique triplets.

It appears that the MSVC library generates a result with an error
of 1 unit in the least significant place for hypot(99.0, 20.0).
There is very little that Tcl can do about bugs in the underlying
C library.

I'm getting seriously tired of reimplementing C library functions
because the vendors can't be troubled to make them actually work.

By the way, you *do* realize that there are much better ways to
generate Pythagorean triples?

If m and n are relatively prime, m > n, and exactly one of m and
n is even, then

a = mn, b = m**2 - n**2, c = m**2 + n**2

is a primitive Pythagorean triple, and all three sides can be
multiplied by any integer to yield more Pythagorean triples.
No square rooting or other floating point machination needed.

--
73 de ke9tv/2, Kevin
From: Robert Heller on
At Fri, 4 Sep 2009 09:58:19 -0700 (PDT) solar <solaradmin2009(a)gmail.com> wrote:

>
> Hi,
>
> There seems to be a bug in the way numbers are compared in Tcl.
> Consider the below script for calculating Pythagorean triplets.
> For hypotenuse upto a value of 100, there should have been 63
> unique triplets.
>
> On Windows XP the script detects only 62. The script doesn't detect
> the case where c=99, b=20 ==> a=101.
>
> However running the same script under Tcl 8.4.1 in Cygwin detects
> 63 triplets.
>
> I don't have a Linux machine at hand to test it there.
>
> Following is the script and relevant output. Could anyone shed some
> light
> on the cause of this. Maybe it has something to do with how the
> numbers
> are represented internally?

Not likely.

I get 63 both with native linux (tcl_patchLevel = 8.4.7) and using a
Tclkit.exe running under Wine (tcl_patchLevel = 8.4.12).

>
> Running the script for N>100 shows up many more such missed values.
> An equivalent program in C runs correctly on the same machine. C code
> was compiled using both gcc and VC++6.0.
>
>
> #########################################################################
> # a^2 = b^2 + c^2
> proc pythag {MAX} {
> set i 0
> for {set c 2} {$c <= $MAX} {incr c} {
> for {set b 1} {$b < $c} {incr b} {
> set a [expr hypot($c, $b)] ;# Calc. Hypot
>
> if { ($c == 99) && ($b == 20)} { ;# <<<<<<<<
> puts ">> [expr round($a)] == $a"
> }
>
> if {[expr round($a)] == $a} {
*I* would suspect this line.
You are comparing with *equality* a
floating point number. That is often bad
news. Remember, the the *computer* is using
finite presision *binary* floating point numbers
the results are not *mathematically*
what you might expect... All it would
take would be some guard bit jitter to
completely ruin your day... Maybe you
want (I'm suspecting that 101.0 is
really 101.00000000001, which is != 101:
if {[expr round($a)] == [expr {int(a)}]} {
> puts "$a : $b : $c"
> incr i
> }
> }
> }
> return $i
> }
>
> if {$argc == 1} {
> set MAX [lindex $argv 0]
> } else {
> puts stderr "Usage: tclsh $argv0 N"
> exit
> }
>
> puts [pythag $MAX]
>
> ############# OUTPUT ################
> Tcl 8.4.1 (Cygwin)
> ------------------------
> 5.0 : 3 : 4
> 10.0 : 6 : 8
> <snip>
> 104.0 : 40 : 96
> 120.0 : 72 : 96
> >> 101 == 101.0
> 101.0 : 20 : 99
> 125.0 : 75 : 100
> 63
>
> Tcl 8.4.18 (Activestate Dist.)
> ---------------------
> 5.0 : 3 : 4
> 10.0 : 6 : 8
> <snip>
> 104.0 : 40 : 96
> 120.0 : 72 : 96
> >> 101 == 101.0
> 125.0 : 75 : 100
> 62
>
> Tcl 8.5.2 (Activestate Dist.)
> ----------------------
> 5.0 : 3 : 4
> 10.0 : 6 : 8
> <snip>
> 104.0 : 40 : 96
> 120.0 : 72 : 96
> >> 101 == 100.99999999999999
> 125.0 : 75 : 100
> 62
> ###########################################
>
>
> TIA
> --
>

--
Robert Heller -- 978-544-6933
Deepwoods Software -- Download the Model Railroad System
http://www.deepsoft.com/ -- Binaries for Linux and MS-Windows
heller(a)deepsoft.com -- http://www.deepsoft.com/ModelRailroadSystem/