• Re: Why does cube root from negative number fails in Tcl?

    From Robert Heller@heller@deepsoft.com to comp.lang.tcl on Wed Dec 3 22:50:54 2025
    From Newsgroup: comp.lang.tcl

    At Wed, 3 Dec 2025 22:19:06 -0000 (UTC) gazelle@shell.xmission.com (Kenny McCormack) wrote:

    In article <10gkad1$1dori$1@dont-email.me>,
    Eric Hassold <hassold@evopulse.com> wrote:
    ...
    But on any system and language (Tcl being one among many, if not all) >operating on real numbers, the result can only be NaN.

    All that you wrote makes sense, but, interestingly enough, both Perl and
    AWK (GAWK) get this right:

    % iPerl
    :-) -8 ** (1/3)
    -2
    :-) ^C
    % gawk4 'BEGIN { print -8 ** (1/3) }'
    -2
    %

    I haven't dug into it, but (unless I'm assuming something I should not be assuming), I would expect both of them to be using pow() to do the work.
    Also Common Lisp:
    sbcl
    This is SBCL 1.4.2, an implementation of ANSI Common Lisp.
    More information about SBCL is available at <http://www.sbcl.org/>.
    SBCL is free software, provided as is, with absolutely no warranty.
    It is mostly in the public domain; some portions are provided under
    BSD-style licenses. See the CREDITS and COPYING files in the
    distribution for more information.
    * (expt -8 1/3)
    #C(1.0 1.7320508)
    *
    --
    Robert Heller -- Cell: 413-658-7953 GV: 978-633-5364
    Deepwoods Software -- Custom Software Services
    http://www.deepsoft.com/ -- Linux Administration Services
    heller@deepsoft.com -- Webhosting Services
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Tristan Wibberley@tristan.wibberley+netnews2@alumni.manchester.ac.uk to comp.lang.tcl on Thu Dec 4 03:10:52 2025
    From Newsgroup: comp.lang.tcl

    On 01/12/2025 14:57, Eric Hassold wrote:

    ... at system level, since calculating pow(-8.0,1.0/3.0) operates on
    floating point numbers, the exponent is not known anymore to be a
    rational number when pow() is calculated.


    Are there irrational floating-point numbers? I thought every
    floating-point number (obviously not NaNs and infs) was a rational.

    In your example the exponent is a rational number even if it's:

    3333333333333333/10000000000000000

    as it appears to be on my local Tcl version:

    expr {1.0/3.0}
    0.3333333333333333
    --
    Tristan Wibberley

    The message body is Copyright (C) 2025 Tristan Wibberley except
    citations and quotations noted. All Rights Reserved except that you may,
    of course, cite it academically giving credit to me, distribute it
    verbatim as part of a usenet system or its archives, and use it to
    promote my greatness and general superiority without misrepresentation
    of my opinions other than my opinion of my greatness and general
    superiority which you _may_ misrepresent. You definitely MAY NOT train
    any production AI system with it but you may train experimental AI that
    will only be used for evaluation of the AI methods it implements.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Christian Gollwitzer@auriocus@gmx.de to comp.lang.tcl on Thu Dec 4 07:15:13 2025
    From Newsgroup: comp.lang.tcl

    Am 03.12.25 um 23:19 schrieb Kenny McCormack:
    In article <10gkad1$1dori$1@dont-email.me>,
    Eric Hassold <hassold@evopulse.com> wrote:
    ...
    But on any system and language (Tcl being one among many, if not all)
    operating on real numbers, the result can only be NaN.

    All that you wrote makes sense, but, interestingly enough, both Perl and
    AWK (GAWK) get this right:

    % iPerl
    :-) -8 ** (1/3)
    -2
    :-) ^C
    % gawk4 'BEGIN { print -8 ** (1/3) }'
    -2
    %


    I think this is a misunderstanding. They compute -(8**(1/3)) instead of (-8)**(1/3)

    chris@linux:~> gawk 'BEGIN {print (-8)**(1.0/3)}'
    -nan
    chris@linux:~>

    Whereas in Tcl, the - sign binds stronger than the exponent operator **
    - I think, this is a bug (or misdesign).


    I haven't dug into it, but (unless I'm assuming something I should not be assuming), I would expect both of them to be using pow() to do the work.

    The problem is that even if you go to the complex domain, the principle
    root is a different one:

    https://www.wolframalpha.com/input?i=%28-8%29%5E%281%2F3%29

    says 1+sqrt(3)*i


    The pow operator cannot see anymore that teh exponent is a fraction with
    an odd denominator (unless it would try to rewrite the floating point
    value into a fraction) - therefore the only reliable way to do this
    would be a nthroot function like this:

    proc nthroot {x n} {
    if {![string is entier $n]} {
    return -code error "ONly integer exponents"
    }
    if {$x >= 0} {
    return [expr {$x**(1.0/$n)}]
    }
    if {$n % 2 == 0} { return -code error "Even root from negative number" }

    return [expr {-(abs($x)**(1.0/$n))}]
    }

    Christian
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From meshparts@alexandru.dadalau@meshparts.de to comp.lang.tcl on Thu Dec 4 07:51:19 2025
    From Newsgroup: comp.lang.tcl

    Am 04.12.2025 um 07:15 schrieb Christian Gollwitzer:
    therefore the only reliable way to do this would be a nthroot function
    like this:
    Well, if this is the only solution, then Tcl needs such a function.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Eric Hassold@hassold@evopulse.com to comp.lang.tcl on Thu Dec 4 00:43:42 2025
    From Newsgroup: comp.lang.tcl

    On 12/3/25 19:10, Tristan Wibberley wrote:
    On 01/12/2025 14:57, Eric Hassold wrote:

    ... at system level, since calculating pow(-8.0,1.0/3.0) operates on
    floating point numbers, the exponent is not known anymore to be a
    rational number when pow() is calculated.


    Are there irrational floating-point numbers? I thought every
    floating-point number (obviously not NaNs and infs) was a rational.

    In your example the exponent is a rational number even if it's:

    3333333333333333/10000000000000000

    as it appears to be on my local Tcl version:

    expr {1.0/3.0}
    0.3333333333333333


    Sure, every IEEE754 number is de facto a rational number:

    value = (Signbit ? -1 : 1) * (1 + Mantissa) * 2^(Exponent - 1023)

    But that rational number is not (necessarily) equal to the initial
    rational number, and the parity of its numerator/denominator is not
    preserved.

    Let's take this 1.0/3.0. The calculated IEEE754 number is:
    (0, 01111111101, 0101010101010101010101010101010101010101010101010101)
    that is:
    (1 + (0x5555555555555 / 2**52)) * 2^(1021 - 1023)
    or, in pure fractional form:
    0x15555555555555 / (2**54)
    and, if converted back to decimal, is exactly:
    0.333333333333333314829616256247390992939472198486328125

    What about 1.0/6.0? well, very similar, we end up with:
    0x15555555555555 / (2**55)
    i.e., in decimal:
    0.1666666666666666574148081281236954964697360992431640625

    Then the issue is clear. Those two numbers have same parity (odd
    numerator, even denominator), not correlated with the parity of their
    original fractional form (odd for 1/3, even for 1/6). So if trying to
    evaluate say pow(-8.0, 1.0/3.0) and pow(-64, 1.0/6.0), it is impossible
    to determine, from the IEEE754-encoded "fractional form", that the
    former may return -2 but the latter should fail.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.tcl on Thu Dec 4 12:37:09 2025
    From Newsgroup: comp.lang.tcl

    In article <10gr8tj$10ea$1@dont-email.me>,
    Christian Gollwitzer <auriocus@gmx.de> wrote:
    ...
    I think this is a misunderstanding. They compute -(8**(1/3)) instead of >(-8)**(1/3)

    chris@linux:~> gawk 'BEGIN {print (-8)**(1.0/3)}'
    -nan
    chris@linux:~>

    Oops. You are right. My mistake.

    When you parenthesize (-8), both AWK and Perl report "nan".

    It really had not occurred to me that - would bind less tightly than **.

    As they say, Never Mind...

    Though, having said all this, it makes one wonder what OP's actual use case was. I don't think that was ever explained. I mean, what I am saying is
    that the simplest solution to OP's problem is just to re-parenthesize his expression:

    expect 1.2> expr -8 ** (1.0/3)
    Error: domain error: argument not in valid range
    expect 1.3> expr -(8 ** (1.0/3))
    Result: -2.0
    expect 1.4>

    Voila! Problem solved.

    (Yes, this is intended as a satire of the tendency (*) on support forums (including Usenet) of focusing on providing a workaround instead of
    addressing the actual question...)

    (*) Though not seen in this thread. In general, I find the TCL group significantly *less* persnickety than is usual... That's a Good Thing.
    --
    b w r w g y b r y b
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From meshparts@alexandru.dadalau@meshparts.de to comp.lang.tcl on Thu Dec 4 13:57:03 2025
    From Newsgroup: comp.lang.tcl

    Am 04.12.2025 um 13:37 schrieb Kenny McCormack:
    Though, having said all this, it makes one wonder what OP's actual use case was. I don't think that was ever explained. I mean, what I am saying is that the simplest solution to OP's problem is just to re-parenthesize his expression:

    expect 1.2> expr -8 ** (1.0/3)
    Error: domain error: argument not in valid range
    expect 1.3> expr -(8 ** (1.0/3))
    Result: -2.0
    expect 1.4>

    Voila! Problem solved.
    As you already imagined, this will not solve my problem.
    I fixed this in my code by if/else and asking about the sign of the base.
    In general Tcl has no standard function to correctly compute $a**(1.0/$b).
    I think this needs to be solved.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From gazelle@gazelle@shell.xmission.com (Kenny McCormack) to comp.lang.tcl on Thu Dec 4 13:05:22 2025
    From Newsgroup: comp.lang.tcl

    In article <10gs0f8$14a4k$1@tota-refugium.de>,
    meshparts <alexandru.dadalau@meshparts.de> wrote:
    Am 04.12.2025 um 13:37 schrieb Kenny McCormack:
    Though, having said all this, it makes one wonder what OP's actual use case >> was. I don't think that was ever explained. I mean, what I am saying is
    that the simplest solution to OP's problem is just to re-parenthesize his
    expression:

    expect 1.2> expr -8 ** (1.0/3)
    Error: domain error: argument not in valid range
    expect 1.3> expr -(8 ** (1.0/3))
    Result: -2.0
    expect 1.4>

    Voila! Problem solved.
    As you already imagined, this will not solve my problem.
    I fixed this in my code by if/else and asking about the sign of the base.

    Note: I don't know enough TCL to know the actual names/syntax for what I am proposing, but it seems you could do something like:

    sgn(x)*(abs(x) ** (1.0/n))

    Editorial comment: IMHO, sgn() is an often useful function that should be present in our toolkits. It is sad that most such toolkits omit it.

    In general Tcl has no standard function to correctly compute $a**(1.0/$b).
    I think this needs to be solved.

    Agreed.
    --
    Elect a clown, expect a circus.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From meshparts@alexandru.dadalau@meshparts.de to comp.lang.tcl on Thu Dec 4 16:58:23 2025
    From Newsgroup: comp.lang.tcl

    Am 04.12.2025 um 14:05 schrieb Kenny McCormack:
    Note: I don't know enough TCL to know the actual names/syntax for what I am proposing, but it seems you could do something like:

    sgn(x)*(abs(x) ** (1.0/n))

    Hm, I guess not. Only true if n is odd.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From meshparts@alexandru.dadalau@meshparts.de to comp.lang.tcl on Thu Dec 4 16:59:42 2025
    From Newsgroup: comp.lang.tcl

    Am 04.12.2025 um 14:05 schrieb Kenny McCormack:
    In article <10gs0f8$14a4k$1@tota-refugium.de>,
    meshparts <alexandru.dadalau@meshparts.de> wrote:
    Am 04.12.2025 um 13:37 schrieb Kenny McCormack:
    Though, having said all this, it makes one wonder what OP's actual use case >>> was. I don't think that was ever explained. I mean, what I am saying is >>> that the simplest solution to OP's problem is just to re-parenthesize his >>> expression:

    expect 1.2> expr -8 ** (1.0/3)
    Error: domain error: argument not in valid range
    expect 1.3> expr -(8 ** (1.0/3))
    Result: -2.0
    expect 1.4>

    Voila! Problem solved.
    As you already imagined, this will not solve my problem.
    I fixed this in my code by if/else and asking about the sign of the base.

    Note: I don't know enough TCL to know the actual names/syntax for what I am proposing, but it seems you could do something like:

    sgn(x)*(abs(x) ** (1.0/n))

    Editorial comment: IMHO, sgn() is an often useful function that should be present in our toolkits. It is sad that most such toolkits omit it.

    In general Tcl has no standard function to correctly compute $a**(1.0/$b). >> I think this needs to be solved.

    Agreed.

    Christian Gollwitzer already proposed a user defined function to solve
    this: nthroot
    But this function should be standard in Tcl.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Harald Oehlmann@wortkarg3@yahoo.com to comp.lang.tcl on Fri Dec 5 10:57:51 2025
    From Newsgroup: comp.lang.tcl

    Am 04.12.2025 um 16:59 schrieb meshparts:
    Am 04.12.2025 um 14:05 schrieb Kenny McCormack:
    In article <10gs0f8$14a4k$1@tota-refugium.de>,
    meshparts  <alexandru.dadalau@meshparts.de> wrote:
    Am 04.12.2025 um 13:37 schrieb Kenny McCormack:
    Though, having said all this, it makes one wonder what OP's actual
    use case
    was.  I don't think that was ever explained.  I mean, what I am
    saying is
    that the simplest solution to OP's problem is just to re-
    parenthesize his
    expression:

    expect 1.2> expr -8 ** (1.0/3)
    Error: domain error: argument not in valid range
    expect 1.3> expr -(8 ** (1.0/3))
    Result: -2.0
    expect 1.4>

    Voila!  Problem solved.
    As you already imagined, this will not solve my problem.
    I fixed this in my code by if/else and asking about the sign of the
    base.

    Note: I don't know enough TCL to know the actual names/syntax for what
    I am
    proposing, but it seems you could do something like:

         sgn(x)*(abs(x) ** (1.0/n))

    Editorial comment: IMHO, sgn() is an often useful function that should be
    present in our toolkits.  It is sad that most such toolkits omit it.

    In general Tcl has no standard function to correctly compute
    $a**(1.0/$b).
    I think this needs to be solved.

    Agreed.

    Christian Gollwitzer already proposed a user defined function to solve
    this: nthroot
    But this function should be standard in Tcl.

    We need a TCL ticket for this.

    Any voluntears ?

    Thanks,
    Harald

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From meshparts@alexandru.dadalau@meshparts.de to comp.lang.tcl on Fri Dec 5 15:33:21 2025
    From Newsgroup: comp.lang.tcl

    Am 05.12.2025 um 10:57 schrieb Harald Oehlmann:
    We need a TCL ticket for this.

    Any voluntears ?
    I could write an email to tcl-core, would that suffice?
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Tristan Wibberley@tristan.wibberley+netnews2@alumni.manchester.ac.uk to comp.lang.tcl on Sat Dec 6 17:10:47 2025
    From Newsgroup: comp.lang.tcl

    On 04/12/2025 08:43, Eric Hassold wrote:
    On 12/3/25 19:10, Tristan Wibberley wrote:
    On 01/12/2025 14:57, Eric Hassold wrote:

    ... at system level, since calculating pow(-8.0,1.0/3.0) operates on
    floating point numbers, the exponent is not known anymore to be a
    rational number when pow() is calculated.


    Are there irrational floating-point numbers? I thought every
    floating-point number (obviously not NaNs and infs) was a rational.

    In your example the exponent is a rational number even if it's:

       3333333333333333/10000000000000000

    as it appears to be on my local Tcl version:

       expr {1.0/3.0}
       0.3333333333333333


    Sure

    So the exponent is still known to be a rational number. Did you start by
    saying "exponent" instead of whatever term refers to the result of an exponentiation? I think that would then have been correct.


    every IEEE754 number is de facto a rational number:

    Is IEEE754 relevant? Does Tcl use IEEE754 or just whatever system of floating-point calculation is fast on the hardware?


    I won't bother commenting on your very detailed text below because I
    don't have fully toned mental machinery to recognise everything quickly
    the way it's written but I appreciate it for later.



       value = (Signbit ? -1 : 1) * (1 + Mantissa) * 2^(Exponent - 1023)

    But that rational number is not (necessarily) equal to the initial
    rational number, and the parity of its numerator/denominator is not preserved.

    Let's take this 1.0/3.0. The calculated IEEE754 number is:
      (0, 01111111101, 0101010101010101010101010101010101010101010101010101) that is:
      (1 + (0x5555555555555 / 2**52)) * 2^(1021 - 1023)
    or, in pure fractional form:
      0x15555555555555 / (2**54)
    and, if converted back to decimal, is exactly:
      0.333333333333333314829616256247390992939472198486328125

    What about 1.0/6.0? well, very similar, we end up with:
      0x15555555555555 / (2**55)
    i.e., in decimal:
      0.1666666666666666574148081281236954964697360992431640625

    Then the issue is clear. Those two numbers have same parity (odd
    numerator, even denominator), not correlated with the parity of their original fractional form (odd for 1/3, even for 1/6). So if trying to evaluate say pow(-8.0, 1.0/3.0) and pow(-64, 1.0/6.0), it is impossible
    to determine, from the IEEE754-encoded "fractional form", that the
    former may return -2 but the latter should fail.
    --
    Tristan Wibberley

    The message body is Copyright (C) 2025 Tristan Wibberley except
    citations and quotations noted. All Rights Reserved except that you may,
    of course, cite it academically giving credit to me, distribute it
    verbatim as part of a usenet system or its archives, and use it to
    promote my greatness and general superiority without misrepresentation
    of my opinions other than my opinion of my greatness and general
    superiority which you _may_ misrepresent. You definitely MAY NOT train
    any production AI system with it but you may train experimental AI that
    will only be used for evaluation of the AI methods it implements.

    --- Synchronet 3.21a-Linux NewsLink 1.2