floating point numbers on C vs. Perl 
Author Message
 floating point numbers on C vs. Perl

This is a school related assignment ( all 10 lines of it! ). In C the
following code works as expected, exiting the loop after 'oldsum' and 'sum'
are equal to each other:

#include <stdio.h>
// I'm not a gifted C programmer yet...
int main ( void )

 float sum = 0;
 float oldsum = 0;
 int counter = 0;
    do {
        oldsum = sum;
        counter++;
        sum += 1.0 / counter;
    } while ( sum != oldsum );
 printf("Sum of 1/N => %.20f, counter => %d\n", sum, counter);
 return 0;

Quote:
}

And the corresponding Perl code is very similiar:

use strict;
 my $old_sum = 0.0;
 my $sum = 0.0;
 my $counter = 0;
 do {
     $old_sum = $sum;
     $counter++;
     $sum += 1.0 / $counter;
 } while ( $old_sum != $sum );

 print "$sum \t $old_sum\n"; # loop never terminates

The Perl code does not terminate ( well it will terminate eventually but I
dion't want to wait a week ). The C code seems to be 'less precise' i.e. the
numbers are far less accurate than Perl's so the loop is able to exit after
about 2million interations ( roughly two or three seconds ). Perl's numbers
are much more exact and causing the loop to run for unacceptably long time.

Is there someway I can make Perl less precise? Some sort of pragma? I've
looked at the POSIX float constants but didn't see anything that caught my
eye. I've tried:

     $sum += sprintf("%.4f", 1.0 / $counter);

And playing around with the %g operator for sprintf() but to no avail. I've
searched on CPAN for some sort of module or documentation that might help,
the CD Bookshelf, and my Mastering Algorithms With Perl book. These are some
of my settings:

   intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    alignbytes=8, usemymalloc=y, prototype=define

Ideas?
Ron



Wed, 18 Jun 1902 08:00:00 GMT  
 floating point numbers on C vs. Perl

Quote:

>  } while ( $old_sum != $sum );

  When using float/double, never compare for exact equality, always
use a range:
   ABS (val1 - val2) > eps

where eps is eg 1e-06

When I modified the C program to use doubles too it ran a long time:
   742.61u 0.01s 12:24.37 99.7%
the Perl version has been running for 22 minutes and isn't done yet,
and I'm running out of patience as well ;)

Erik



Wed, 18 Jun 1902 08:00:00 GMT  
 floating point numbers on C vs. Perl

MCMXCIII in <URL::">
-- This is a school related assignment ( all 10 lines of it! ). In C the
-- following code works as expected, exiting the loop after 'oldsum' and 'sum'
-- are equal to each other:
--
-- #include <stdio.h>
-- // I'm not a gifted C programmer yet...

That shows, as // isn't C, but C++ ....

-- int main ( void )
--
--  float sum = 0;
--  float oldsum = 0;
--  int counter = 0;
--     do {
--         oldsum = sum;
--         counter++;
--         sum += 1.0 / counter;
--     } while ( sum != oldsum );

This is a bad idea in C as well. Just because your compiler/platform
combination uses a certain amount of bits to represent floats doesn't
mean the next platform uses 32 as many bits.

--  printf("Sum of 1/N => %.20f, counter => %d\n", sum, counter);
--  return 0;
-- }
--
-- And the corresponding Perl code is very similiar:
--
-- use strict;
--  my $old_sum = 0.0;
--  my $sum = 0.0;
--  my $counter = 0;
--  do {
--      $old_sum = $sum;
--      $counter++;
--      $sum += 1.0 / $counter;
--  } while ( $old_sum != $sum );
--
--  print "$sum \t $old_sum\n"; # loop never terminates

No, it isn't. The corresponding C code for the above would be:

    # include <stdio.h>

    int main (int argc, char* argv []) {
        double sum, oldsum;
        int    counter;
        sum     = 0.0;
        counter = 0;
        do {
            oldsum = sum;
            sum   += 1.0 / ++ counter;
        } while (sum != oldsum);

        printf ("%.15g \t %.15g\n", sum, counter);
        return 0;
    }

which, not very surprisingly, takes a while to terminate too.

-- The Perl code does not terminate ( well it will terminate eventually but I
-- dion't want to wait a week ). The C code seems to be 'less precise' i.e. the
-- numbers are far less accurate than Perl's so the loop is able to exit after
-- about 2million interations ( roughly two or three seconds ). Perl's numbers
-- are much more exact and causing the loop to run for unacceptably long time.

Actually, both Perl and C use the same underlying datatypes. Except that
the datatype is a double, not a float.

-- Is there someway I can make Perl less precise? Some sort of pragma? I've

Making Perl less precise isn't the answer. The answer is to fix the idea
that comparing floats or doubles for (in)equality is a good idea.

Do something like:

    #!/opt/perl/bin/perl -w
    use strict;
    use constant EPSILON  =>  5E-7;
    my $old_sum = 0;
    my $sum     = 0;
    my $counter = 0;
    do {
        $old_sum = $sum;
        $sum    += 1 / ++ $counter;
    } while abs ($sum - $old_sum) > EPSILON;

    printf "Sum of 1/N => %.20f, counter => %d\n" => $sum, $counter;

    __END__

With as equivalent C code:

    # include <stdio.h>
    # include <math.h>

    # define EPSILON  (5e-7)

    int main (int argc, char* argv []) {
        double sum, oldsum;
        int    counter;
        sum     = 0.0;
        counter = 0;
        do {
            oldsum = sum;
            sum   += 1.0 / ++ counter;
        } while (fabs (sum - oldsum) > EPSILON);

        printf ("Sum of 1/N => %.20f, counter => %d\n", sum, counter);
        return 0;
    }

Running the Perl version gives:
    Sum of 1/N => 15.08587365342573104535, counter => 2000000
Running the C version gives:
    Sum of 1/N => 15.08587415342456417022, counter => 2000001

Note that the C version is *much* faster. 11.21 user time for Perl vs
0.24 user time for C on my system. That's almost 50 times faster.

Abigail

--
perl -we'$;=$";$;{Just=>another=>Perl=>Hacker=>}=$/;print%;'
#    A dragon waiting.
#    A spider crawling in a
#    maple tree. A dog.



Wed, 18 Jun 1902 08:00:00 GMT  
 floating point numbers on C vs. Perl

Quote:


> MCMXCIII in <URL::">
> -- This is a school related assignment ( all 10 lines of it! ). In C the
> -- following code works as expected, exiting the loop after 'oldsum' and 'sum'
> -- are equal to each other:
> --
> -- #include <stdio.h>
> -- // I'm not a gifted C programmer yet...

> That shows, as // isn't C, but C++ ....

careful with the sarcasm ... that form is valid in c99 ... and the
person
is in college so maybe that's what's being taught nowadays ;)


Wed, 18 Jun 1902 08:00:00 GMT  
 floating point numbers on C vs. Perl

Quote:
> careful with the sarcasm ... that form is valid in c99 ... and the
> person
> is in college so maybe that's what's being taught nowadays ;)

Abigail has a valid point. I was fully prepated take a lashing for my
bad code. I'm actually using g++ as my compiler but I failed to mention
that. I did know that // is not a valid C comment btw :)


Wed, 18 Jun 1902 08:00:00 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. Handling floating point number input in Perl CGI scripts

2. Handling floating point number input in Perl CGI scripts

3. Help with some arithmetic : Integer vs. Floating point

4. rounding floating point numbers

5. Floating Points and Large Numbers...

6. unpacking IEEE 437 Floating point numbers

7. TOY: explore the representation of binary floating point numbers

8. floating point number format...

9. Q: getting the decimal portion of a floating point number

10. Floating Point Number With Time Function

11. comparing floating point numbers

12. floating point number precision?

 

 
Powered by phpBB® Forum Software