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

Does Perl formally support exponential notation for octal numbers? #18664

Closed
briandfoy opened this issue Mar 26, 2021 · 16 comments · May be fixed by #23097
Closed

Does Perl formally support exponential notation for octal numbers? #18664

briandfoy opened this issue Mar 26, 2021 · 16 comments · May be fixed by #23097

Comments

@briandfoy
Copy link
Member

Description

perldata does not mention a octal floating point form, but apparently it works:

$ perl5.32.0 -le 'print 01.4441766521041321410646114314242700334p+1'
3.14159265358979
$ perl5.33.8 -le 'print 0o1.4441766521041321410646114314242700334p+1'
3.14159265358979

Is this intended? If so, it should be added to the list of scalar value constructors.

If this is not intended, I guess it should stop doing that.

Perl configuration

Summary of my perl5 (revision 5 version 32 subversion 1) configuration:
   
  Platform:
    osname=darwin
    osvers=19.3.0
    archname=darwin-2level
    uname='darwin otter.local 19.3.0 darwin kernel version 19.3.0: thu jan 9 20:58:23 pst 2020; root:xnu-6153.81.5~1release_x86_64 x86_64 '
    config_args='-des -Dprefix=/usr/local/perls/perl-5.32.1'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=undef
    usemultiplicity=undef
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -DPERL_USE_SAFE_PUTENV'
    optimize='-O3'
    cppflags='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='4.2.1 Compatible Apple LLVM 11.0.3 (clang-1103.0.32.62)'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags =' -mmacosx-version-min=10.15 -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/11.0.3/lib /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib /usr/lib
    libs=-lpthread -ldbm -ldl -lm -lutil -lc
    perllibs=-lpthread -ldl -lm -lutil -lc
    libc=
    so=dylib
    useshrplib=false
    libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=bundle
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags=' -mmacosx-version-min=10.15 -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector-strong'


Characteristics of this binary (from libperl): 
  Compile-time options:
    HAS_TIMES
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    PERL_USE_SAFE_PUTENV
    USE_64_BIT_ALL
    USE_64_BIT_INT
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
  Built under darwin
  Compiled at Mar 21 2021 18:45:32
  %ENV:
    PERL="/Users/brian/bin/perls/perl-latest"
    PERL5_PATH="/Users/brian/bin/perls"
    PERL6_PATH="/Users/brian/bin/perl6s:/Applications/Rakudo/bin:/Applications/Rakudo/share/perl6/site/bin"
    PERLDOTCOM_AUTHOR="brian-d-foy"
    PERLSCHOOL_AUTHOR="brian d foy"
  @INC:
    /usr/local/perls/perl-5.32.1/lib/site_perl/5.32.1/darwin-2level
    /usr/local/perls/perl-5.32.1/lib/site_perl/5.32.1
    /usr/local/perls/perl-5.32.1/lib/5.32.1/darwin-2level
    /usr/local/perls/perl-5.32.1/lib/5.32.1
@sisyphus
Copy link
Contributor

Based on some quick, non-extensive testing, it seems that both the octal and hex forms of floating point (bareword) values are no longer a fatal error as of perl-5.22.0.
However, the implementation of both octals and hexadecimals was buggy in that release.
For perl-5.x.0 (x >= 24), octals and hexadecimals seem to be treated correctly, though this requires that the 'p+exponent' part is specified in addition to the '0' or '0x' exponent.

I'd be hopeful that this could be attended to by amending the documentation as needed.

briandfoy added a commit that referenced this issue Mar 26, 2021
If this is officially supported (#18664), here's a patch for the docs.
@pjacklam
Copy link
Contributor

For perl-5.x.0 (x >= 24), octals and hexadecimals seem to be treated correctly, though this requires that the 'p+exponent' part is specified in addition to the '0' or '0x' exponent.

On Cygwin built with quadmath, binary and octal floating point literals were silently treated as hexadecimals before 5.28.0. From 5.28.0 and onwards, both binary, octal, and hexadecimals seem to work correctly. (And from 5.33.5 and onwards, the "0o" prefix is supported.)

@t-a-k
Copy link
Contributor

t-a-k commented Mar 26, 2021

Not surprisingly, perl also accepts binary floating point literals.

$ perl -wle 'print 0b1.1001001000011111101101010100010001000010110100011000p1'
3.14159265358979

In addition, currently perl does not seem to provide a standard way to convert floats to octal/binary form. IMHO it might be better to note in the document that the conversions are one-way.

@pjacklam
Copy link
Contributor

pjacklam commented Mar 26, 2021

In addition, currently perl does not seem to provide a standard way to convert floats to octal/binary form.

Going the other way is not straight forward because of limitations in the way perl handles floating point literals. For example, here is the number with the smallest magnitude using binary64 (a.k.a. double) floating point numbers:

$ perl -wle 'print 0x0.0000000000001p-1022'
4.94065645841247e-324

The following represents the same number. A warning is given, but the result is correct.

$ perl -wle 'print 0x1p-1074'
Hexadecimal float: exponent underflow at -e line 1.
4.94065645841247e-324

The following also represents the same number. Again a warning is given, but the result is incorrect.

$ perl -wle 'print 0x0.00000000000001p-1018'
Hexadecimal float: mantissa overflow at -e line 1.
0

By the way, all three representations work fine if perl is compiled with quadmath support, but of course in that case the numbers are no longer the smallest possible magnitude.

@tonycoz
Copy link
Contributor

tonycoz commented Mar 29, 2021

perldata does not mention a octal floating point form, but apparently it works:

$ perl5.32.0 -le 'print 01.4441766521041321410646114314242700334p+1'
3.14159265358979
$ perl5.33.8 -le 'print 0o1.4441766521041321410646114314242700334p+1'
3.14159265358979

Is this intended? If so, it should be added to the list of scalar value constructors.

It's not clear to me whether support for octal/binary floating point literals were intended when the code was originally written, or it just naturally came about from the way the implementation is integrated into the implementation of parsing hex/octal/binary integers.

We have fixed some bugs specific to octal/binary floating point literals, so considering them supported and documenting them is reasonable.

@sisyphus
Copy link
Contributor

For me. on Windows (building perl with mingw-w64 ports of gcc-8.3.0) the "0o" formatting (but not the "0x" or "0") is invalid prior to perl-5.33.5:

C:\>perl -le "print $]"
5.033004

C:\>perl -V:gccversion
gccversion='8.3.0';

C:\>perl -le "print 0o1.4441766521041321410646114314242700334p+1"
Bareword found where operator expected at -e line 1, near "0o1"
        (Missing operator before o1?)
Bareword found where operator expected at -e line 1, near "4441766521041321410646114314242700334p"
        (Missing operator before p?)
syntax error at -e line 1, near "0o1"
Execution of -e aborted due to compilation errors.

C:\>perl -le "print 0o1.4441766521041321410646114314242700334"
Bareword found where operator expected at -e line 1, near "0o1"
        (Missing operator before o1?)
syntax error at -e line 1, near "0o1"
Execution of -e aborted due to compilation errors.

Is it the same on other systems ?

Also, when the 'p+exponent' part is left out, the decimal point is taken to be the dot operator, which seems a little odd:

C:\>perl -wle "print 01.55p+0"
1.703125

C:\>perl -wle "print 01.55"
155

C:\>perl -wle "print 015.5"
135

A similar thing happens wrt to "0x":

C:\>perl -wle "print 0x1.55p+0"
1.33203125

C:\>perl -wle "print 0x1.55"
155

C:\>perl -wle "print 0x15.5"
215

And then for me (perl-5.33.5 and later only):

C:\>perl -le "print 0o1.444p+0"
1.5703125

C:\>perl -le "print 0o1.444"
1444

C:\>perl -le "print 0o14.44"
1244

It's a pity about that. Can it be covered via documentation ? ... or do we need to look at altering the behaviour ?

@pjacklam
Copy link
Contributor

For me. on Windows […]
Is it the same on other systems ?

It is the same on Cygwin (as I mentioned above). It should be the same on all systems, since the support for the "0o" prefix was introduced with the commit b728918 between v5.33.4 and v5.33.5.

Also, when the 'p+exponent' part is left out, the decimal point is taken to be the dot operator, which seems a little odd:

C:\>perl -wle "print 01.55p+0"
1.703125

C:\>perl -wle "print 01.55"
155

C:\>perl -wle "print 015.5"
135

At least this is as documented. The literal is only treated as a floating point number if the exponent is present. As a consequence, if the exponent is not present, the bin/oct/hex number is treated as an integer.

@sisyphus
Copy link
Contributor

sisyphus commented Mar 29, 2021 via email

@briandfoy
Copy link
Member Author

Closing this as inactive so it's not in my list of open issues.

@karenetheridge
Copy link
Member

If this is documented, I'm not seeing it...

@pjacklam
Copy link
Contributor

pjacklam commented Mar 9, 2025

If this is documented, I'm not seeing it...

Neither do I. The examples in perldata.pod (see below) ought to mention octal and binary floating point literals. Just one example of each below the hexadecimal floating point example would be useful.

  Scalar value constructors
    Numeric literals are specified in any of the following floating point or
    integer formats:

     (…)
     0377                # octal (only numbers, begins with 0)
     0o12_345            # alternative octal (introduced in Perl 5.33.5)
     0b011011            # binary
     0x1.999ap-4         # hexadecimal floating point (the 'p' is required)

A few paragraphs further down I find the following, which ought to mention octal and binary floating point literals in addition to hexadecimal:

    Hexadecimal floating point can start just like a hexadecimal literal,
    and it can be followed by an optional fractional hexadecimal part, but
    it must be followed by "p", an optional sign, and a power of two.
    (…)

@pjacklam
Copy link
Contributor

pjacklam commented Mar 9, 2025

What is going on? If Perl supports octal and binary floating point literals – and this is not documented – I cannot see how this issue can be seen as completed.

@briandfoy
Copy link
Member Author

briandfoy commented Mar 10, 2025

It's not completed, and it can't be completed. It's just closed. Either someone has to decide that Perl supports this and we document it, or no one makes the decision and we don't document it and accept it as a curious side effect that perl may later not support.

It's been four years without no decision. No decision is the decision that perl doesn't guarantee support for this and it's a curiousity. It's not completed; it's closed. Later, if someone makes the decision to support it, they can document it.

It's basic issue management to not let tickets live forever, especially if there will be no action on them. Unactionable long-lived tickets pollute the backlog such that people don't mind more unactionable long-lived tickets, and eventually this makes the accumulating backlog so noisy that even good tickets drown in it. And, not only does this pollute the perl queue, but also the list of issues I have under my own username.

As such, I don't want this unactionable issue in my personal backlog. It's a problem for me working toward zero inbox.

@pjacklam
Copy link
Contributor

I see your point.

I don't know who has the authority to say that binary and octal floating point literals are officially supported, but I'd like to point out that both binary and octal floating point literals are tested in t/op/hexfp.t. I don't know if that means they are officially supported, though.

@Grinnz
Copy link
Contributor

Grinnz commented Mar 10, 2025

Constant overloads for them were fixed in 5.32 (#14791) so I believe that is sufficient indication that they are intentionally supported.

@mauke
Copy link
Contributor

mauke commented Mar 10, 2025

It's not completed, and it can't be completed.

Then don't mark it as "completed".

mauke added a commit to mauke/perl5 that referenced this issue Mar 10, 2025
This (possibly accidental) feature has had tests since commit
58be576 and bug fixes such as commit 2cb5a7e. See also the
discussion in GH issues Perl#16114 and Perl#14791, particularly jhi's comment in
<Perl#16114 (comment)>:

> Relatedly: I remember there being a known "loophole" so that the
> scanning code currently accidentally, falling naturally out of the
> implementation, is also doing "binary fp" and "octal fp". Ah yes:
>
>     ./miniperl -wle 'print 0b11.1p0'
>     3.5
>     ./miniperl -wle 'print 011.1p0'
>     9.125
>
> This is probably not documented anywhere. I can't now think of the
> right search terms to find any previous discussion, there was something
> about should this be rejected, or not. If not (as is currently the
> case), maybe this possibly should be tested, documented, and made
> official?

With the documentation in this patch and the existing tests, I guess the
feature is now official.

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

Successfully merging a pull request may close this issue.

9 participants