Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rounding error after division #1900

Closed
p5pRT opened this issue Apr 26, 2000 · 7 comments
Closed

rounding error after division #1900

p5pRT opened this issue Apr 26, 2000 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 26, 2000

Migrated from rt.perl.org#3170 (status was 'resolved')

Searchable as RT3170$

@p5pRT
Copy link
Author

p5pRT commented Apr 26, 2000

From ortmann@sparc.isl.net

Created by ortmann@pyrl.eye

Unexpected "int"ification caused a program crash at work today.
I submit this for your consideration and possible resolution​:

perl -le '
print q[expect to get 707​:];
$n = 1272.6 / 1.8;
print $n, q[ <= 1272.6 / 1.8];
print int $n, q[ <= int $n];
print "$n <= inside a string";
$n = "$n";
print $n, q[ <= after $n = "$n" sets a string context];
$n = 1272.6 / 1.8;
$n += 0.0;
print int $n, q[ <= int $n after $n += 0.0]
'

expect to get 707​:
707 <= 1272.6 / 1.8
706 <= int $n
707 <= inside a string
707 <= after $n = "$n" sets a string context
706 <= int $n after $n += 0.0

1) I assume this is caused by slight truncation error due to base 2.
2) Perhaps there is IEEE floating point status information which might
  be used to un-do the truncation error?
3) The successful addition of 0.0 seems to support idea #2.
4) It seems strange that "$n" is a better "int" than int($n), although
  it is also slower.

Perl Info


Site configuration information for perl 5.00557:

Configured by ortmann at Mon May 31 22:49:25 CDT 1999.

Summary of my perl5 (revision 5.0 version 5 subversion 57) configuration:
  Platform:
    osname=freebsd, osvers=4.0-current, archname=i386-freebsd
    uname='freebsd pyrl.eye 4.0-current freebsd 4.0-current #1: sun may 9 23:52:53 cdt 1999 root@pyrl.eye:usrsrcsrcsyscompilepyrl i386 '
    config_args=''
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef useperlio=undef d_sfio=undef
    use64bits=undef usemultiplicity=undef
  Compiler:
    cc='cc', optimize='-O', gccversion=egcs-2.91.66 19990314 (egcs-1.1.2 release)
    cppflags='-I/usr/local/include'
    ccflags ='-I/usr/local/include'
    stdchar='char', d_stdstdio=undef, usevfork=true
    intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    alignbytes=4, usemymalloc=y, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-Wl,-E  -L/usr/local/lib'
    libpth=/usr/lib /usr/local/lib
    libs=-lgdbm -lm -lc -lcrypt
    libc=/usr/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-DPIC -fpic', lddlflags='-shared  -L/usr/local/lib'

Locally applied patches:
    


@INC for perl 5.00557:
    /usr/local/lib/perl5/5.00557/i386-freebsd
    /usr/local/lib/perl5/5.00557
    /usr/local/lib/perl5/site_perl/5.00557/i386-freebsd
    /usr/local/lib/perl5/site_perl/5.00557
    .


Environment for perl 5.00557:
    HOME=/home/ortmann
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH=/usr/lib:/usr/local/lib/kaffe
    LOGDIR (unset)
    PATH=/home/ortmann/bin:/usr/local/script:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/bin:/usr/bin
    PERL_BADLANG (unset)
    SHELL=/usr/local/bin/bash


@p5pRT
Copy link
Author

p5pRT commented Apr 26, 2000

From [Unknown Contact. See original ticket]

4) It seems strange that "$n" is a better "int" than int($n), although
it is also slower.

  DB<1> $x = 5.999999999999999
  DB<2> print $x
6
  DB<3> print int($x)
5
  DB<4> printf "%.20f", $x
5.99999999999999911182

So?

Perhaps a stronger form of "use integer" should be the default
mode of numbers in Perl.

--tom

@p5pRT
Copy link
Author

p5pRT commented Apr 26, 2000

From @tamias

On Wed, Apr 26, 2000 at 10​:22​:38PM -0500, Daniel Ortmann wrote​:

Unexpected "int"ification caused a program crash at work today.

perldoc -q decimal

=head2 Why am I getting long decimals (eg, 19.9499999999999) instead of the
numbers I should be getting (eg, 19.95)?

The infinite set that a mathematician thinks of as the real numbers can
only be approximate on a computer, since the computer only has a finite
number of bits to store an infinite number of, um, numbers.

Internally, your computer represents floating-point numbers in binary.
Floating-point numbers read in from a file or appearing as literals
in your program are converted from their decimal floating-point
representation (eg, 19.95) to the internal binary representation.

However, 19.95 can't be precisely represented as a binary
floating-point number, just like 1/3 can't be exactly represented as a
decimal floating-point number. The computer's binary representation
of 19.95, therefore, isn't exactly 19.95.

When a floating-point number gets printed, the binary floating-point
representation is converted back to decimal. These decimal numbers
are displayed in either the format you specify with printf(), or the
current output format for numbers (see L<perlvar/"$#"> if you use
print. C<$#> has a different default value in Perl5 than it did in
Perl4. Changing C<$#> yourself is deprecated.

This affects B<all> computer languages that represent decimal
floating-point numbers in binary, not just Perl. Perl provides
arbitrary-precision decimal numbers with the Math​::BigFloat module
(part of the standard Perl distribution), but mathematical operations
are consequently slower.

To get rid of the superfluous digits, just use a format (eg,
C<printf("%.2f", 19.95)>) to get the required precision.
See L<perlop/"Floating-point Arithmetic">.

@p5pRT
Copy link
Author

p5pRT commented Apr 27, 2000

From [Unknown Contact. See original ticket]

perldoc -q decimal

=head2 Why am I getting long decimals (eg, 19.9499999999999) instead
of the numbers I should be getting (eg, 19.95)?

I am well aware of rounding issues. Restating​:

print "$n" # displays an implicitly rounded number
print int $n # behaves differently than above

No problem. I'll probably try something like the following​:

use subs qw( int );
sub int {
  my $n = shift;
  $n = CORE​::int $n;
  "$n"
}

I just thought I'd bring up the difference in case y'all wanted to make
int() behave differently.

Thanks

@p5pRT
Copy link
Author

p5pRT commented Apr 27, 2000

From @tamias

On Thu, Apr 27, 2000 at 06​:58​:14PM -0500, Daniel Ortmann wrote​:

perldoc -q decimal

=head2 Why am I getting long decimals (eg, 19.9499999999999) instead
of the numbers I should be getting (eg, 19.95)?

I am well aware of rounding issues. Restating​:

Then I am at a loss as to your bug report.

print "$n" # displays an implicitly rounded number
print int $n # behaves differently than above

"$n" does an implicit sprintf. sprintf() rounds floating point arguments.
int() truncates them, as documented.

=item int EXPR

=item int

Returns the integer portion of EXPR. If EXPR is omitted, uses C<$_>.
You should not use this function for rounding​: one because it truncates
towards C<0>, and two because machine representations of floating point
numbers can sometimes produce counterintuitive results. For example,
C<int(-6.725/0.025)> produces -268 rather than the correct -269; that's
because it's really more like -268.99999999999994315658 instead. Usually,
the C<sprintf()>, C<printf()>, or the C<POSIX​::floor> and C<POSIX​::ceil>
functions will serve you better than will int().

No problem. I'll probably try something like the following​:

use subs qw( int );
sub int {
my $n = shift;
$n = CORE​::int $n;
"$n"
}

I don't think that will have the result you seem to intend. If you want to
round, use one of the solutions suggested in the documentation.

I just thought I'd bring up the difference in case y'all wanted to make
int() behave differently.

int() truncates, as it should.

Ronald

@p5pRT
Copy link
Author

p5pRT commented May 2, 2003

From @iabyn

not-a-bug

@p5pRT
Copy link
Author

p5pRT commented May 2, 2003

@iabyn - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant