decimal round off issue

Discussion in 'Perl Misc' started by Shiping Zhang, Sep 22, 2009.

  1. Is this a bug in perl?

    $v = sprintf "%.1f", 2.25;
    print $v, "\n";

    The above code produced 2.2

    $v = sprintf "%.1f", 2.35;
    print $v, "\n";

    The above code produced 2.4

    I tested several versions, they all behaved the same.
     
    Shiping Zhang, Sep 22, 2009
    #1
    1. Advertising

  2. Shiping Zhang <> wrote:
    >Is this a bug in perl?
    >
    >$v = sprintf "%.1f", 2.25;
    >print $v, "\n";
    >
    >The above code produced 2.2


    I cannot reproduce this observation. For me it prints 2.3.
    ( v5.10.0 built for MSWin32-x86-multi-thread)

    >$v = sprintf "%.1f", 2.35;
    >print $v, "\n";
    >
    >The above code produced 2.4
    >
    >I tested several versions, they all behaved the same.


    However more than likely you don't even need the sprintf() assignment
    with separate print(), a simple
    printf "%.1f", 2.35;
    will most likely behave exactly the same.

    If so then try
    printf "%.40f", 2.25;
    and
    printf "%.40f", 2.35;
    on your Perl installation. This will most likely demonstrate the reason
    for your observation. For an explanation please
    - see "perldoc -q 999"
    - re-read your notes from "Introduction into Computer Numerics"
    - check the NG archives for dozens and dozens of similar posts and the
    replies to them

    jue
     
    Jürgen Exner, Sep 22, 2009
    #2
    1. Advertising

  3. On 9ÔÂ22ÈÕ, ÏÂÎç1ʱ08·Ö, Shiping Zhang <> wrote:
    > Is this a bug in perl?
    >
    > $v = sprintf "%.1f", 2.25;
    > print $v, "\n";
    >
    > The above code produced 2.2
    >
    > $v = sprintf "%.1f", 2.35;
    > print $v, "\n";
    >
    > The above code produced 2.4
    >
    > I tested several versions, they all behaved the same.


    Okay, it's not a bug. This is due to limitation of machine (binary)
    representation of floating point numbers. A test C program behaved
    the same.
     
    Shiping Zhang, Sep 22, 2009
    #3
  4. Shiping Zhang

    Guest

    On Tue, 22 Sep 2009 12:52:36 -0700 (PDT), Shiping Zhang <> wrote:

    >On 9ÔÂ22ÈÕ, ÏÂÎç1ʱ08·Ö, Shiping Zhang <> wrote:
    >> Is this a bug in perl?
    >>
    >> $v = sprintf "%.1f", 2.25;
    >> print $v, "\n";
    >>
    >> The above code produced 2.2
    >>
    >> $v = sprintf "%.1f", 2.35;
    >> print $v, "\n";
    >>
    >> The above code produced 2.4
    >>
    >> I tested several versions, they all behaved the same.

    >
    >Okay, it's not a bug. This is due to limitation of machine (binary)
    >representation of floating point numbers. A test C program behaved
    >the same.


    Right, a binary thing! But more than that, different results across
    different floating point hardware, firmware, libs.

    You would think all things being equal, the same error pattern should
    be had on all machines.

    The good news is that internal fp operations wash out those discrepenccies
    well past the number of digits of which the real universe can actually
    be measured by physical means. Ie, its not right/wrong unless you can
    prove it is/isn't. There are probably wider (bit-wise) floating point
    registers available for calculations on scientific principles that can't
    be proven.

    c:\>perl -e "for(2.15,2.25,2.35,2.45,2.55,2.65) {$v = sprintf \"%.1f\", $_;
    print \"$v\n\"}"
    2.1
    2.3
    2.4
    2.5
    2.5
    2.6

    -sln
     
    , Sep 22, 2009
    #4
  5. Shiping Zhang

    Guest

    On Tue, 22 Sep 2009 14:42:09 -0700, John Stanley <> wrote:

    >
    >On Tue, 22 Sep 2009, Shiping Zhang wrote:
    >
    >> On 9?22?, ??1?08?, Shiping Zhang <> wrote:
    >>> Is this a bug in perl?
    >>>
    >>> $v = sprintf "%.1f", 2.25;
    >>> print $v, "\n";
    >>>
    >>> The above code produced 2.2
    >>>...

    >
    >> Okay, it's not a bug. This is due to limitation of machine (binary)
    >> representation of floating point numbers. A test C program behaved
    >> the same.

    >
    >I don't think I missed class that day, but what binary representation of
    >floating point CANNOT represent the base ten number "2.25"? That's 10.01
    >base two.
    >

    Thats very true. And its non-repeating. Therefore, it should not be a
    problem going from (1.001 x 2**1)base 2, to 2.25 base 10 and having it display
    correctly when it comes to rounding and formatting string representation.
    I'm not sure that rounding happens the same way on all systems when there is
    a repeting binary fraction (like .55 base 10).

    From wikipedia: http://en.wikipedia.org/wiki/IEEE_754-1985

    I wonder if you do a bitwise examination of a float variable if it
    will show the sign, exp, fraction bits like in the standard?
    Or on the language level, are the bitwise operators restricted to
    operations on integers?

    Where are the calculators that do binary <-> decimal fractions?
    Don't want to do it by hand all the time.

    -sln
     
    , Sep 23, 2009
    #5
  6. Jürgen Exner wrote:
    > Shiping Zhang <> wrote:
    >> Is this a bug in perl?
    >>
    >> $v = sprintf "%.1f", 2.25;
    >> print $v, "\n";
    >>
    >> The above code produced 2.2

    >
    > I cannot reproduce this observation. For me it prints 2.3.
    > ( v5.10.0 built for MSWin32-x86-multi-thread)


    v5.8,8 running on Kubuntu 8.04LTS has the same peculiarity:

    $v = sprintf "%.1f", 2.25;
    print $v, "\n";
    $v = sprintf "%.1f", 2.35;
    print $v, "\n";

    2.2
    2.4

    --
    These are my personal views and not those of Fujitsu Technology Solutions!
    Josef Möllers (Pinguinpfleger bei FTS)
    If failure had no penalty success would not be a prize (T. Pratchett)
    Company Details: http://de.ts.fujitsu.com/imprint.html
     
    Josef Moellers, Sep 23, 2009
    #6
  7. On 2009-09-22 17:34, Jürgen Exner <> wrote:
    > Shiping Zhang <> wrote:
    >>Is this a bug in perl?
    >>
    >>$v = sprintf "%.1f", 2.25;
    >>print $v, "\n";
    >>
    >>The above code produced 2.2

    >
    > I cannot reproduce this observation. For me it prints 2.3.
    > ( v5.10.0 built for MSWin32-x86-multi-thread)


    Strange. It should produce 2.2 (2.25 is exactly halfway between 2.2 and
    2.3, so the "round to even" rule is used). However, 2.2 and 2.3 aren't
    exactly representable, so maybe that's where the rounding error is.

    On Debian Linux (perl, v5.10.0 built for i486-linux-gnu-thread-multi),
    this:

    perl -e 'for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf "%.60f %.1f\n", $_, $_ }'

    prints:

    2.149999999999999911182158029987476766109466552734375000000000 2.1
    2.250000000000000000000000000000000000000000000000000000000000 2.2
    2.350000000000000088817841970012523233890533447265625000000000 2.4
    2.450000000000000177635683940025046467781066894531250000000000 2.5
    2.549999999999999822364316059974953532218933105468750000000000 2.5
    2.649999999999999911182158029987476766109466552734375000000000 2.6
    2.750000000000000000000000000000000000000000000000000000000000 2.8
    2.850000000000000088817841970012523233890533447265625000000000 2.9
    2.950000000000000177635683940025046467781066894531250000000000 3.0

    which is exactly correct: The values which are slightly above or below
    0.x5 are rounded up or down as appropriate, and 2.25 and 2.75 are
    rounded to even.

    hp
     
    Peter J. Holzer, Sep 23, 2009
    #7
  8. Shiping Zhang

    Guest

    On Wed, 23 Sep 2009 19:21:08 +0200, "Peter J. Holzer" <> wrote:

    >On 2009-09-22 17:34, Jürgen Exner <> wrote:
    >> Shiping Zhang <> wrote:
    >>>Is this a bug in perl?
    >>>
    >>>$v = sprintf "%.1f", 2.25;
    >>>print $v, "\n";
    >>>
    >>>The above code produced 2.2

    >>
    >> I cannot reproduce this observation. For me it prints 2.3.
    >> ( v5.10.0 built for MSWin32-x86-multi-thread)

    >
    >Strange. It should produce 2.2 (2.25 is exactly halfway between 2.2 and
    >2.3, so the "round to even" rule is used). However, 2.2 and 2.3 aren't
    >exactly representable, so maybe that's where the rounding error is.
    >
    >On Debian Linux (perl, v5.10.0 built for i486-linux-gnu-thread-multi),
    >this:
    >
    >perl -e 'for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf "%.60f %.1f\n", $_, $_ }'
    >
    >prints:
    >
    >2.149999999999999911182158029987476766109466552734375000000000 2.1
    >2.250000000000000000000000000000000000000000000000000000000000 2.2
    >2.350000000000000088817841970012523233890533447265625000000000 2.4
    >2.450000000000000177635683940025046467781066894531250000000000 2.5
    >2.549999999999999822364316059974953532218933105468750000000000 2.5
    >2.649999999999999911182158029987476766109466552734375000000000 2.6
    >2.750000000000000000000000000000000000000000000000000000000000 2.8
    >2.850000000000000088817841970012523233890533447265625000000000 2.9
    >2.950000000000000177635683940025046467781066894531250000000000 3.0
    >
    >which is exactly correct: The values which are slightly above or below
    >0.x5 are rounded up or down as appropriate, and 2.25 and 2.75 are
    >rounded to even.
    >
    > hp


    I never heard of that "round to even" rule. On my build it rounds "up"
    all the time. Maybe I don't have the latest build.

    perl -e "for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf \"%.60f %.1f\n\", $_, $_ }"

    2.149999999999999900000000000000000000000000000000000000000000 2.1
    2.250000000000000000000000000000000000000000000000000000000000 2.3
    2.350000000000000100000000000000000000000000000000000000000000 2.4
    2.450000000000000200000000000000000000000000000000000000000000 2.5
    2.549999999999999800000000000000000000000000000000000000000000 2.5
    2.649999999999999900000000000000000000000000000000000000000000 2.6
    2.750000000000000000000000000000000000000000000000000000000000 2.8
    2.850000000000000100000000000000000000000000000000000000000000 2.9
    2.950000000000000200000000000000000000000000000000000000000000 3.0

    I'm sure this is a result of a define flag passed via compiler option.
    I' got the active state 5.10 built using gcc. I looked over the build
    parameters using perl -V. I've only used MS compilers, so I don't know
    some of the options listed. I looked for optimizations that I recognized,
    only saw O2, compile for speed. MS has some /FP: optimizations like
    precise/strict,etc.., that gcc doesen't.
    Gcc looks like it has nvtype as double, its size 64 bit.
    ----------------
    v5.10.0 built for MSWin32-x86-multi-thread
    (with 5 registered patches)

    Binary build 1004 [287188] provided by ActiveState http://www.ActiveState.com
    Built Sep 3 2008 13:16:37
    --------------

    -sln
     
    , Sep 23, 2009
    #8
  9. On 2009-09-23 19:21, <> wrote:
    > On Wed, 23 Sep 2009 19:21:08 +0200, "Peter J. Holzer" <> wrote:
    >>On 2009-09-22 17:34, Jürgen Exner <> wrote:
    >>> Shiping Zhang <> wrote:
    >>>>Is this a bug in perl?
    >>>>
    >>>>$v = sprintf "%.1f", 2.25;
    >>>>print $v, "\n";
    >>>>
    >>>>The above code produced 2.2
    >>>
    >>> I cannot reproduce this observation. For me it prints 2.3.
    >>> ( v5.10.0 built for MSWin32-x86-multi-thread)

    >>
    >>Strange. It should produce 2.2 (2.25 is exactly halfway between 2.2 and
    >>2.3, so the "round to even" rule is used). However, 2.2 and 2.3 aren't
    >>exactly representable, so maybe that's where the rounding error is.
    >>
    >>On Debian Linux (perl, v5.10.0 built for i486-linux-gnu-thread-multi),
    >>this:
    >>
    >>perl -e 'for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf "%.60f %.1f\n", $_, $_ }'
    >>
    >>prints:
    >>
    >>2.149999999999999911182158029987476766109466552734375000000000 2.1
    >>2.250000000000000000000000000000000000000000000000000000000000 2.2
    >>2.350000000000000088817841970012523233890533447265625000000000 2.4
    >>2.450000000000000177635683940025046467781066894531250000000000 2.5
    >>2.549999999999999822364316059974953532218933105468750000000000 2.5
    >>2.649999999999999911182158029987476766109466552734375000000000 2.6
    >>2.750000000000000000000000000000000000000000000000000000000000 2.8
    >>2.850000000000000088817841970012523233890533447265625000000000 2.9
    >>2.950000000000000177635683940025046467781066894531250000000000 3.0
    >>
    >>which is exactly correct: The values which are slightly above or below
    >>0.x5 are rounded up or down as appropriate, and 2.25 and 2.75 are
    >>rounded to even.

    >
    > I never heard of that "round to even" rule.


    It is mentioned in this group just about every time that rounding is
    discussed, which is probably at least once or twice per year.

    The rule was used at least since the early 20th century (Wikipedia cites
    a book from 1906). In IEEE-754 arithmetic (which is used in all current
    FP units) it is the default rounding mode.

    > On my build it rounds "up"
    > all the time. Maybe I don't have the latest build.
    >
    > perl -e "for(2.15,2.25,2.35,2.45,2.55,2.65, 2.75, 2.85, 2.95) {printf \"%.60f %.1f\n\", $_, $_ }"
    >
    > 2.149999999999999900000000000000000000000000000000000000000000 2.1
    > 2.250000000000000000000000000000000000000000000000000000000000 2.3
    > 2.350000000000000100000000000000000000000000000000000000000000 2.4
    > 2.450000000000000200000000000000000000000000000000000000000000 2.5
    > 2.549999999999999800000000000000000000000000000000000000000000 2.5
    > 2.649999999999999900000000000000000000000000000000000000000000 2.6
    > 2.750000000000000000000000000000000000000000000000000000000000 2.8
    > 2.850000000000000100000000000000000000000000000000000000000000 2.9
    > 2.950000000000000200000000000000000000000000000000000000000000 3.0
    >
    > I'm sure this is a result of a define flag passed via compiler option.


    More likely it's caused by the implementation of sprintf in the C
    library.

    > I' got the active state 5.10 built using gcc. I looked over the build
    > parameters using perl -V.


    Is there a "standard" C library on Windows which gcc has to use or does
    it use the glibc? I suspect it's the former (I've seen similar results
    with Microsofts C compiler).

    hp
     
    Peter J. Holzer, Sep 23, 2009
    #9
  10. On 2009-09-24, Ben Morrow <> wrote:
    > Huh? glibc is Linux- (well, and Hurd-) only.


    Last time I compiled glibc was several years ago. But it was nowhere
    close to Linux and/or Hurd. It is just a C library on top of POSIX -
    at lest at was at the time...

    > gcc on Win32 uses MSVCRT.DLL,


    AFAIK, there are many gcc's on Win32, all (?) using different CRTL...

    Yours,
    Ilya
     
    Ilya Zakharevich, Sep 24, 2009
    #10
  11. Shiping Zhang

    Guest

    On Wed, 23 Sep 2009 22:51:36 +0200, "Peter J. Holzer" <> wrote:

    >On 2009-09-23 19:21, <> wrote:
    >> On Wed, 23 Sep 2009 19:21:08 +0200, "Peter J. Holzer" <> wrote:
    >>>On 2009-09-22 17:34, Jürgen Exner <> wrote:
    >>>> Shiping Zhang <> wrote:

    <snip>
    >> I never heard of that "round to even" rule.

    >
    >It is mentioned in this group just about every time that rounding is
    >discussed, which is probably at least once or twice per year.
    >
    >The rule was used at least since the early 20th century (Wikipedia cites
    >a book from 1906). In IEEE-754 arithmetic (which is used in all current
    >FP units) it is the default rounding mode.
    >

    Yeah I just read that on wikipedia. I imagine that a fpu has
    at least 2, 80 bit registers to do comarisons, +-/* operations,
    and result (don't know about this at all).
    When the fraction is to be chopped to 64 bit variable, the lsb
    is set to 0, if the lsb-1 bit in the register is set, not sure.
    It says 'midway'.
    I don't thinks this is a fp rounding issue, since by the standard,
    this would be consistent across fp hardware.

    >> On my build it rounds "up"
    >> all the time. Maybe I don't have the latest build.
    >> I'm sure this is a result of a define flag passed via compiler option.

    >
    >More likely it's caused by the implementation of sprintf in the C
    >library.
    >

    I think you are right on it being a lib implementation issue.

    >> I' got the active state 5.10 built using gcc. I looked over the build
    >> parameters using perl -V.

    >
    >Is there a "standard" C library on Windows which gcc has to use or does
    >it use the glibc? I suspect it's the former (I've seen similar results
    >with Microsofts C compiler).
    >
    > hp


    There is a standard set of dll's that comes with Windows os',
    2004 seems to be the last year that CRT was modified (added to).
    Some older programs used to just include some runtime libs (dll's) in thier
    exe path.

    Microsoft defines 'core' dll's (crt, win32 interface, etc..) in thier os,
    that get put in the system32 dir, part of the system path.

    Most programs that link to them use import .lib 's.
    That was seen all over gcc. Most can just get the platform sdk and
    grab the lib's. Header files are a whole different nightmare.

    So, yes. Gcc links with msvcrt.lib (import) which loads the system
    dll when it runs. Single threaded static libc is no longer available
    since VC2002/3/5/...

    But gcc uses /MD multithread-dynamic CRT library option. So thats
    where it is.

    In all of MS compilers, there is the option to compile as either
    C or C++. It looks like Gcc compiles it as C.
    I have VC-2005.

    Still, you have to wonder why MS, who supposedly is ANSI CRT
    would differ from other compilers in its sprintf results.
    I thought it could be that gcc doesn't use perhaps an optimization
    that MS uses in its comiler that may pertain to floating point.

    On the other hand, there is alot of defines being passed to the
    Perl source. Are you sure that sprintf/printf from the CRT is
    is not being bypassed via custom Perl implementation?

    Either way, it might be nice to compile it under vc-2005,
    using the float option /FP:precision

    -sln

    ---<cut>-------
    c:\temp>perl -V

    Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
    Platform:
    osname=MSWin32, osvers=5.00, archname=MSWin32-x86-multi-thread
    uname=''
    config_args='undef'
    hint=recommended, useposix=true, d_sigaction=undef
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
    Compiler:
    cc='cl', ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -DWIN32 -D_CONSOLE -
    DNO_STRICT -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE -DPRIVLIB_LAST_IN_INC -DPERL_IM
    PLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -DPERL_MSVCRT_READFIX',
    optimize='-MD -Zi -DNDEBUG -O1',
    cppflags='-DWIN32'
    ccversion='12.0.8804', gccversion='', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', lseeksi
    ze=8
    alignbytes=8, prototype=define
    Linker and Libraries:
    ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf -libpath:"C:
    \Perl\lib\CORE" -machine:x86'
    libpth=\lib
    libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32
    ..lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_
    32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib
    perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comd
    lg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib
    ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib
    libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl510.lib
    gnulibc_version=''
    Dynamic Linking:
    dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug -opt:ref,icf -
    libpath:"C:\Perl\lib\CORE" -machine:x86'


    Characteristics of this binary (from libperl):
    Compile-time options: MULTIPLICITY PERL_DONT_CREATE_GVSV
    PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS
    PERL_MALLOC_WRAP PL_OP_SLAB_ALLOC USE_ITHREADS
    USE_LARGE_FILES USE_PERLIO USE_SITECUSTOMIZE
    Locally applied patches:
    ActivePerl Build 1004 [287188]
    33741 avoids segfaults invoking S_raise_signal() (on Linux)
    33763 Win32 process ids can have more than 16 bits
    32809 Load 'loadable object' with non-default file extension
    32728 64-bit fix for Time::Local
    Built under MSWin32
    Compiled at Sep 3 2008 13:16:37
    @INC:
    C:/Perl/site/lib
    C:/Perl/lib
     
    , Sep 24, 2009
    #11
  12. Shiping Zhang

    Guest

    On Wed, 23 Sep 2009 18:58:39 -0700, wrote:

    >---<cut>-------


    c:\temp>perl -v

    This is perl, v5.10.0 built for MSWin32-x86-multi-thread
    (with 5 registered patches, see perl -V for more detail)

    Copyright 1987-2007, Larry Wall

    Binary build 1004 [287188] provided by ActiveState http://www.ActiveState.com
    Built Sep 3 2008 13:16:37

    Perl may be copied only under the terms of either the Artistic License or the
    GNU General Public License, which may be found in the Perl 5 source kit.

    Complete documentation for Perl, including FAQ lists, should be found on
    this system using "man perl" or "perldoc perl". If you have access to the
    Internet, point your browser at http://www.perl.org/, the Perl Home Page.


    c:\temp>

    >c:\temp>perl -V
    >
    >Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
    > Platform:
    > osname=MSWin32, osvers=5.00, archname=MSWin32-x86-multi-thread
    > uname=''
    > config_args='undef'
    > hint=recommended, useposix=true, d_sigaction=undef
    > useithreads=define, usemultiplicity=define
    > useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    > use64bitint=undef, use64bitall=undef, uselongdouble=undef
    > usemymalloc=n, bincompat5005=undef
    > Compiler:
    > cc='cl', ccflags ='-nologo -GF -W3 -MD -Zi -DNDEBUG -O1 -DWIN32 -D_CONSOLE -
    >DNO_STRICT -DHAVE_DES_FCRYPT -DUSE_SITECUSTOMIZE -DPRIVLIB_LAST_IN_INC -DPERL_IM
    >PLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -DPERL_MSVCRT_READFIX',
    > optimize='-MD -Zi -DNDEBUG -O1',
    > cppflags='-DWIN32'
    > ccversion='12.0.8804', gccversion='', gccosandvers=''
    > intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    > d_longlong=undef, longlongsize=8, d_longdbl=define, longdblsize=10
    > ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='__int64', lseeksi
    >ze=8
    > alignbytes=8, prototype=define
    > Linker and Libraries:
    > ld='link', ldflags ='-nologo -nodefaultlib -debug -opt:ref,icf -libpath:"C:
    >\Perl\lib\CORE" -machine:x86'
    > libpth=\lib
    > libs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32
    >.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib ws2_
    >32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib
    > perllibs= oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib comd
    >lg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib netapi32.lib uuid.lib
    >ws2_32.lib mpr.lib winmm.lib version.lib odbc32.lib odbccp32.lib msvcrt.lib
    > libc=msvcrt.lib, so=dll, useshrplib=true, libperl=perl510.lib
    > gnulibc_version=''
    > Dynamic Linking:
    > dlsrc=dl_win32.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    > cccdlflags=' ', lddlflags='-dll -nologo -nodefaultlib -debug -opt:ref,icf -
    >libpath:"C:\Perl\lib\CORE" -machine:x86'
    >
    >
    >Characteristics of this binary (from libperl):
    > Compile-time options: MULTIPLICITY PERL_DONT_CREATE_GVSV
    > PERL_IMPLICIT_CONTEXT PERL_IMPLICIT_SYS
    > PERL_MALLOC_WRAP PL_OP_SLAB_ALLOC USE_ITHREADS
    > USE_LARGE_FILES USE_PERLIO USE_SITECUSTOMIZE
    > Locally applied patches:
    > ActivePerl Build 1004 [287188]
    > 33741 avoids segfaults invoking S_raise_signal() (on Linux)
    > 33763 Win32 process ids can have more than 16 bits
    > 32809 Load 'loadable object' with non-default file extension
    > 32728 64-bit fix for Time::Local
    > Built under MSWin32
    > Compiled at Sep 3 2008 13:16:37
    > @INC:
    > C:/Perl/site/lib
    > C:/Perl/lib
    > .
    >
    >c:\temp>
    >
    >
     
    , Sep 24, 2009
    #12
  13. On 2009-09-24 01:10, Ben Morrow <> wrote:
    > Quoth "Peter J. Holzer" <>:
    >> Is there a "standard" C library on Windows which gcc has to use or does
    >> it use the glibc? I suspect it's the former (I've seen similar results
    >> with Microsofts C compiler).

    >
    > Huh? glibc is Linux- (well, and Hurd-) only.


    Ports to other systems existed. I wouldn't be terribly surprised if a
    (partial) port to Windows exists and is bundled with one of the ports of
    gcc for Windows.


    > gcc on Win32 uses MSVCRT.DLL,


    That's what I thought (I wrote "I suspect it's the former"), but I
    didn't know it. The last time I wrote C code for a MS platform was in
    the MS-DOS days ...

    hp
     
    Peter J. Holzer, Sep 26, 2009
    #13
  14. On 2009-09-24 01:58, <> wrote:

    [ unexpected results from perl printf on Windows ]

    > Still, you have to wonder why MS, who supposedly is ANSI CRT
    > would differ from other compilers in its sprintf results.


    The C standard is deliberately vague on many aspects of floating point
    arithmetic, because in the late 1980s there were still a lot of very
    different implementations of fp arithmetic (both in software and
    hardware). Mandating IEEE-754 compliant arithmetic would have been as
    sure way to prevent the standard from being adopted by major vendors.
    Even the C99 standard only contains IEEE-754 arithmetic as an option.

    So the MS printf implementation is almost certainly standard-conforming,
    it just isn't as good as it could be. (I haven't checked, but I think
    the error is below one ulp, so it is even correct)


    > I thought it could be that gcc doesn't use perhaps an optimization
    > that MS uses in its comiler that may pertain to floating point.


    It is unlikely that this has anything to do with compiler optimizations.
    Printf is just implemented differently (note that the MS implementation
    apparently has a fixed number of decimal digits and prints only zeros
    after that).


    > On the other hand, there is alot of defines being passed to the
    > Perl source. Are you sure that sprintf/printf from the CRT is
    > is not being bypassed via custom Perl implementation?


    No. But if Perl had its own implementation I would expect the output on
    Linux and Windows to be the same. Since the output is different it is
    very likely that Perl just uses the facilities of the local C library.

    (The default perl FP->string conversion is a custom implementation
    (since the C library doesn't offer the functionality) and it is buggy -
    I've ranted about that before, but that isn't an issue here)

    hp
     
    Peter J. Holzer, Sep 26, 2009
    #14
  15. On 2009-09-24, Ben Morrow <> wrote:
    >> AFAIK, there are many gcc's on Win32, all (?) using different CRTL...

    >
    > Really? The only port I've ever seen is the MinGW port, which uses
    > MSVCRT as it's libc. (I don't count Cygwin/Interix/whatever gccs as
    > running on Win32, and neither does perl.)


    I saw mentions of djgcc port. At some time OS/2 EMX port was working
    on Win32 with an appropriate syscalls library (RSX-NT, if I remember
    correct) - but later people could not reproduce it; I did not collect
    enough incentive to debug.

    I know that klibc sources have __WIN32__ defines and subdirectories
    scattered about... Do not know whether klibc actually compiles under
    Win32. I know that Perl compiles - and at least in some repects works
    - with klibc.

    Yours,
    Ilya
     
    Ilya Zakharevich, Sep 27, 2009
    #15
  16. On 2009-09-26, Peter J. Holzer <> wrote:
    > (The default perl FP->string conversion is a custom implementation
    > (since the C library doesn't offer the functionality)


    C library definitely offers the functionality. And it was used for
    decades without much problem....

    > and it is buggy -


    Agreed.

    Ilya
     
    Ilya Zakharevich, Sep 27, 2009
    #16
  17. On 2009-09-27 02:46, Ilya Zakharevich <> wrote:
    > On 2009-09-26, Peter J. Holzer <> wrote:
    >> (The default perl FP->string conversion is a custom implementation
    >> (since the C library doesn't offer the functionality)

    >
    > C library definitely offers the functionality.


    Really? Which standard C function gives you the shortest decimal string
    representation of a floating point number which can be be converted back
    to an fp number with the same value?

    The closest I see is gcvt, which isn't a standard C function (but
    probably portable enough for the purposes of perl) and doesn't quite cut
    it either: It prints
    1.0000000000000000818...e-05 as 1.0000000000000001e-05 instead of
    0.00001 or 1e-05 (tested with glibc 2.7).

    hp
     
    Peter J. Holzer, Sep 27, 2009
    #17
  18. On 2009-09-27, Peter J. Holzer <> wrote:
    > On 2009-09-27 02:46, Ilya Zakharevich <> wrote:
    >> On 2009-09-26, Peter J. Holzer <> wrote:
    >>> (The default perl FP->string conversion is a custom implementation
    >>> (since the C library doesn't offer the functionality)

    >>
    >> C library definitely offers the functionality.

    >
    > Really? Which standard C function gives you the shortest decimal string
    > representation of a floating point number which can be be converted back
    > to an fp number with the same value?


    Really? From when "The default perl FP->string conversion" follows
    this requirement? See $# (sp?). [*]

    [*] Of course, it is the ONLY sane semantic for Perl (see perldoc
    perlnumber). However, AFAIK, it is not implemented.

    Here is the history as I know it. About '96 somebody made a patch
    which implemented *this* semantic. With a very noticable slowdown as
    a side effect.

    At the moment I had no idea how numbers are handled in Perl. When (in
    2 or 3 years) I discovered what a mess it is (I wrote an automated
    testing system, and about 60% of sanity tests were failing), I started
    to fix it. Now: a part of the fix was a consistent caching of the
    results of number-->string conversion [**].

    [**] As a resent message about print() shows, it is not THAT
    consistent now...

    With *this* fix in place, switching to slower number-->string
    conversion MIGHT have been cured of significant slowdowns. However,
    myself, I never found tuits to check this.

    Yours,
    Ilya
     
    Ilya Zakharevich, Sep 28, 2009
    #18
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Girish Sahani

    How to truncate/round-off decimal numbers?

    Girish Sahani, Jun 20, 2006, in forum: Python
    Replies:
    15
    Views:
    40,483
    rasonage
    Dec 17, 2011
  2. ஆமாசà¯à®šà¯

    round off to two decimal & return float

    ஆமாசà¯à®šà¯, Mar 30, 2013, in forum: Python
    Replies:
    2
    Views:
    168
    pyplexed
    Mar 30, 2013
  3. ஆமாசà¯à®šà¯

    Re: round off to two decimal & return float

    ஆமாசà¯à®šà¯, Mar 30, 2013, in forum: Python
    Replies:
    1
    Views:
    98
    Grant Edwards
    Mar 30, 2013
  4. Peter Otten
    Replies:
    0
    Views:
    108
    Peter Otten
    Mar 30, 2013
  5. Dennis Lee Bieber

    Re: round off to two decimal & return float

    Dennis Lee Bieber, Mar 30, 2013, in forum: Python
    Replies:
    1
    Views:
    110
Loading...

Share This Page