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

scientific notation parsing/conversion problems #9095

Closed
p5pRT opened this issue Nov 1, 2007 · 8 comments
Closed

scientific notation parsing/conversion problems #9095

p5pRT opened this issue Nov 1, 2007 · 8 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 1, 2007

Migrated from rt.perl.org#47087 (status was 'open')

Searchable as RT47087$

@p5pRT
Copy link
Author

p5pRT commented Nov 1, 2007

From davidp@lanl.gov

This is a bug report for perl from davidp@​lanl.gov,
generated with the help of perlbug 1.35 running under perl v5.8.8.

Upon investigation I've discovered some disturbing things​:

1. perl -e 'print eval($ARGV[0]),"\n"'
'(1.818343814922934E+05-1.818343815129567E+05)/1.450606250000001E+02'
  returns -1.4244604399474e-07
2. Using the attached programs, gcc, pgf90, SunWSPro cc and f90, MIPS f90, gfortran and g95 all
calculate
  the following from the identical expression (on Sun, Cygwin, 32-bit Linux, 64-bit Linux,
SGI)​:
  -1.424458433625532e-07

If that's not disturbing enough, then read on ...

The most disturbing fact occurs when I remove the scientific notation from the literals​:

1. perl -e 'print eval($ARGV[0]),"\n"'
'(181834.3814922934-181834.3815129567)/145.0606250000001'
  returns -1.42445843362553e-07

Compilers are the bane of my life ... sigh.

The following was suggested to me​:

  perl -e 'printf("%.15E\n", eval($ARGV[0])),"\n"' \
  '(1.818343814922934E+05-1.818343815129567E+05)/1.450606250000001E+02'
  -1.424458433625532E-07
  Perl print uses the default C printf precision of six places. To get more you have to
explicitly ask using printf.

It was not portable to Cygwin since my Cygwin build of Perl continued to produce the original,
incorrect value. So, here is an alternative script that avoids the precision problem on all
platforms I've tested so far (i686 Linux, Sun, SGI, i686 Cygwin on Windows XP, IBM AIX Power PC,
Darwin Power PC, i386 Darwin Mac)​:

perl -e '$s=$ARGV[0]; $s=~s/[eE]([+-]?\d+)/*10**$1/g; printf "%s =\n%s
=\n%.15e\n",$ARGV[0],$s,eval($s);' \
  '(1.818343814922934E+05-1.818343815129567E+05)/1.450606250000001E+02'
yields​:
(1.818343814922934E+05-1.818343815129567E+05)/1.450606250000001E+02 =
(1.818343814922934*10**+05-1.818343815129567*10**+05)/1.450606250000001*10**+02 =
-1.424458433625532e-03

Basically, I convert the scientific notation numbers to standard floating point numbers with regex,
and then run eval on the resulting string expression. This indicates to me that "print" is not the
culprit here, but that Perl is not correctly converting scientific notation from the expression.


Flags​:
  category=core
  severity=medium


Site configuration information for perl v5.8.8​:

Configured by rurban at Sun Jul 8 19​:08​:44 GMT 2007.

Summary of my perl5 (revision 5 version 8 subversion 8) configuration​:
  Platform​:
  osname=cygwin, osvers=1.5.24(0.15642), archname=cygwin-thread-multi-64int
  uname='cygwin_nt-5.1 reini 1.5.24(0.15642) 2007-01-31 10​:57 i686 cygwin '
  config_args='-de -Dmksymlinks -Duse64bitint -Dusethreads -Uusemymalloc -Doptimize=-O3
-Dman3ext=3pm -Dusesitecustomize -Dusedevel'
  hint=recommended, useposix=true, d_sigaction=define
  usethreads=define use5005threads=undef useithreads=define usemultiplicity=define
  useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
  use64bitint=define use64bitall=undef uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='gcc', ccflags ='-DPERL_USE_SAFE_PUTENV -fno-strict-aliasing -pipe
-Wdeclaration-after-statement',
  optimize='-O3',
  cppflags='-DPERL_USE_SAFE_PUTENV -fno-strict-aliasing -pipe -Wdeclaration-after-statement'
  ccversion='', gccversion='3.4.4 (cygming special, gdc 0.12, using dmd 0.125)', gccosandvers=''
  intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
  ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='ld2', ldflags =' -s -L/usr/local/lib'
  libpth=/usr/local/lib /usr/lib /lib
  libs=-lgdbm -ldb -ldl -lcrypt -lgdbm_compat
  perllibs=-ldl -lcrypt -lgdbm_compat
  libc=/usr/lib/libc.a, so=dll, useshrplib=true, libperl=libperl.a
  gnulibc_version=''
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' -s'
  cccdlflags=' ', lddlflags=' -s -L/usr/local/lib'

Locally applied patches​:
  CYG01 - hints.cygwin.sh ldflags -s
  CYG02 - lib-ExtUtils-Embed insensitive against leading \\s
  CYG03 - lib-Test-Harness-Straps $ENV{PERL5LIB} = ''
  CYG04 - major.version.cygwin.sh cygperl-5_8.dll and not cygperl-5_8_x.dll
  CYG05 - add Win32CORE to core
  CYG07 - File-Spec-Cygwin-TMPDIR.patch
  Bug#38628 - allow legacy Cwd->cwd()
  Bug#40103 - File-Spec-case_tolerant.patch from 5.9.5


@​INC for perl v5.8.8​:
  /usr/lib/perl5/5.8/cygwin
  /usr/lib/perl5/5.8
  /usr/lib/perl5/site_perl/5.8/cygwin
  /usr/lib/perl5/site_perl/5.8
  /usr/lib/perl5/site_perl/5.8
  /usr/lib/perl5/vendor_perl/5.8/cygwin
  /usr/lib/perl5/vendor_perl/5.8
  /usr/lib/perl5/vendor_perl/5.8
  .


Environment for perl v5.8.8​:
  HOME=/cygdrive/d/Users/120181/cyghome
  LANG (unset)
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)

PATH=/usr/local/bin​:/usr/bin​:/bin​:/cygdrive/c/PROGRA1/GNU/WinCvs​:/eclipse​:/cygdrive/c/absoft90/bin​:
/cygdrive/d/Users/120181/cyghome/SCRIPTS​:/usr/X11R6/bin​:.​:/usr/local/bin​:/usr/local/bin​:/usr/bin​:/bi
n​:/usr/local/bin​:/usr/bin​:/bin​:/usr/X11R6/bin​:/cygdrive/c/Program Files/Microsoft Visual
Studio/Common/Tools​:/cygdrive/c/Program Files/Microsoft Visual
Studio/Common/Msdev98/BIN​:/cygdrive/c/Program Files/Microsoft Visual
Studio/DF98/BIN​:/cygdrive/c/Program Files/Microsoft Visual
Studio/VC98/BIN​:/cygdrive/c/WINDOWS/system32​:/cygdrive/c/WINDOWS​:/cygdrive/c/WINDOWS/System32/Wbem​:/
cygdrive/c/Program Files/ATI Technologies/ATI Control Panel​:/cygdrive/c/Program
Files/WRQ/RSecure/​:/cygdrive/c/Program Files/Reflection/​:/cygdrive/c/Program Files/Diskeeper
Corporation/Diskeeper/​:/cygdrive/c/Program Files/IDM Computer
Solutions/UltraEdit-32​:/cygdrive/c/Program Files/Common Files/Adobe/AGL​:/cygdrive/c/Program
Files/QuickTime/QTSystem/​:/cygdrive/c/Program Files/Common Files/Roxio Shared/!
DLLShared​:/cygdrive/c/Program Files/Microsoft Visual Studio/Common/Tools/WinNT​:/cygdrive/c/Program
Files/Microsoft Visual Studio/Common/MSDev98/Bin​:/cygdrive/c/Program Files/Microsoft Visual
Studio/Common/Tools​:/cygdrive/c/Program Files/Microsoft Visual Studio/VC98/bin​:/cygdrive/c/Program
Files/IDM Computer
Solutions/UltraCompare​:/usr/lib/lapack​:/usr/local/bin/Graphviz/bin​:/usr/local/bin/default/intel-cygw
in​:/cygdrive/d/Users/120181/MYDOCU
1/eospac6/Source/scripts
  PERL_BADLANG (unset)
  SHELL=/bin/tcsh

@p5pRT
Copy link
Author

p5pRT commented Jul 16, 2016

From @dcollinsn

$ perl5.25.2 -e 'print eval("(1.818343814922934E+05-1.818343815129567E+05)"),"\n"'
-2.06633121706545e-05
$ perl5.25.2 -e 'print eval("(181834.3814922934-181834.3815129567)"),"\n"'
-2.06632830668241e-05

What gives?

--
Respectfully,
Dan Collins

@p5pRT
Copy link
Author

p5pRT commented Jul 16, 2016

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jul 16, 2016

From zefram@fysh.org

Dan Collins via RT wrote​:

What gives?

$ perl -MData​::Float=float_hex -le 'print float_hex($_) for 181834.3814922934, 1.818343814922934e5'
+0x1.632530d4bd4dfp+17
+0x1.632530d4bd4dep+17

Looks like another form of [perl #41202]. The former is the true closest
representable value​:

$ perl -le 'printf "%.60f\n", $_ for 181834.3814922934, 1.818343814922934e5'
181834.381492293410701677203178405761718750000000000000000000000000
181834.381492293381597846746444702148437500000000000000000000000000

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jul 17, 2016

From @khwilliamson

On 07/16/2016 05​:40 PM, Zefram wrote​:

Dan Collins via RT wrote​:

What gives?

$ perl -MData​::Float=float_hex -le 'print float_hex($_) for 181834.3814922934, 1.818343814922934e5'
+0x1.632530d4bd4dfp+17
+0x1.632530d4bd4dep+17

Looks like another form of [perl #41202]. The former is the true closest
representable value​:

$ perl -le 'printf "%.60f\n", $_ for 181834.3814922934, 1.818343814922934e5'
181834.381492293410701677203178405761718750000000000000000000000000
181834.381492293381597846746444702148437500000000000000000000000000

-zefram

I've wondered if things like this would be improved if we were to take
the advice of someone whose name I don't recall of treating 10**x as
5**x * 2**x. The first term is much smaller than 10**x, and the second
term is just shifting. But my knowledge of floating point
implementations stopped at the CDC 7600.

@p5pRT
Copy link
Author

p5pRT commented Jul 17, 2016

From zefram@fysh.org

Karl Williamson wrote​:

I've wondered if things like this would be improved if we were to take the
advice of someone whose name I don't recall of treating 10**x as 5**x * 2**x.

No, it would not. When putting multiple digits together, we still need
their weights to be 10**x apart, not 5**x.

-zefram

@khwilliamson
Copy link
Contributor

Please see GH #7586 for a similar issue

@khwilliamson
Copy link
Contributor

RT #41202 (GH #8730 ) was fixed in 5.30. I just ran Dan Collins examples on blead, and both now give the same result. So I'm closing this ticket:

blead -le 'print eval("(1.818343814922934E+05-1.818343815129567E+05)"),"\n"'
-2.06632830668241e-05

blead -le 'print eval("(181834.3814922934-181834.3815129567)"),"\n"'
-2.06632830668241e-05

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

2 participants