1. Little incosistency in Euphoria 2.2

While investigating the value() function and trying to mimic it, I
discovered this little inconsistency:
value("-45.6a-") gives {0,-45.6}
but
value("-45.6e-") gives {1,0}

new topic     » topic index » view message » categorize

2. Re: Little incosistency in Euphoria 2.2

Hmmm... Maybe I'm missing the point (likely, my wife says :)), but isn't 
this post regarding the value() function similar to the last one 
questioning how well value() worked? Similar in that they both feed value() 
some kind of bad data?

Garbage in -> Garbage out.  Maybe we're overloading value() and expecting 
too much?  If so, shouldn't we just write a different, more robust 
function?  I mean, how well does gets(fn) handle a bad sector on a hard 
disk?  Should we expect it to be able to handle ANY input we throw at it?

The 'we' isn't the royal we...It's the Euphoria clan 'we'.   I'm including 
myself as I use the function too...

--Ted

--On Thursday, April 26, 2001 05:20:12 PM -0300 rforno at tutopia.com wrote:

>
>
> While investigating the value() function and trying to mimic it, I
> discovered this little inconsistency:
> value("-45.6a-") gives {0,-45.6}
> but
> value("-45.6e-") gives {1,0}
>
>
>
>
>
>

new topic     » goto parent     » topic index » view message » categorize

3. Re: Little incosistency in Euphoria 2.2

This is a multi-part message in MIME format.

------=_NextPart_000_003F_01C0CF0A.92CCECE0
	charset="iso-8859-1"

I think this is because value() thinks you were going to enter a number =
with a power of ten. eg

value("45.6e2")

should return 4560. =20

------=_NextPart_000_003F_01C0CF0A.92CCECE0
	charset="iso-8859-1"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 5.50.4522.1800" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>I think this is because value() thinks =
you were=20
going to enter a number with a power of ten. eg</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>value("45.6e2")</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>should return 4560.&nbsp;=20

------=_NextPart_000_003F_01C0CF0A.92CCECE0--

new topic     » goto parent     » topic index » view message » categorize

4. Re: Little incosistency in Euphoria 2.2

To avoid errors, value() should ALWAYS return an error message in case
the input string is not fully representing a number (i.e. 12345 or
1e-3). A long time ago I claimed this, but it will not be changed, for
this is the bad heritage of a C-routine behind it!

Have a nice day, Rolf

new topic     » goto parent     » topic index » view message » categorize

5. Re: Little incosistency in Euphoria 2.2


new topic     » goto parent     » topic index » view message » categorize

6. Re: Little incosistency in Euphoria 2.2

----- Original Message -----
From: <rforno at tutopia.com>
To: "EUforum" <EUforum at topica.com>
Subject: RE: Little incosistency in Euphoria 2.2



> I cannot agree with you. If e- is bad, why a- is not?

Because the letter 'e', when it immediately follows a series of digits, is
regarded by value() to be a part of an embedded encoding of a number in
scientific notation. If detected, it MUST be followed by another series of
digits. If not, then value() believes you have a badly formatted number. In
the case of "a-", the 'a' character signals the END of a number and is not
regarded as a part of the number's notation.

However, I agree that this is not the best idea.

Sorry for those who don't long posts but here is an attempt I made at
writing a sequence-to-number conversion. I wanted to use the function
seqtonumber() in an expression so it always returns an atom. To detected
errors, I've had create another function that returns the error position.
Finally, it does not support scientific notation (yet).

----------------------------
integer vBase, vPeriod, vComma, vMoney
sequence vLegalChars
vBase = 10
vPeriod = '.'
vComma = ','
vMoney = '$'
vLegalChars = "0123456789abcdef-+.,"

---
-- Sets the default number base to be used when converting strings to
numbers.
global function setnumberbase(integer pNewBase)
    integer lOldBase

    lOldBase = vBase

    if pNewBase > 1 and pNewBase <= 16 then
        vBase = pNewBase
    end if

    return lOldBase
end function

---
-- Sets the default punctuation characters.
-- If any parameter is zero, then the corresponding punctuation symbol is
not changed.
-- All three punctuation symbols must be different from each other.
-- Returns a sequence of three elements containing the current punctuation
chars.
--   1) The 'decimal place' character. Initially '.'
--   2) The digit separator character. Initially ','
--   3) The money symbol. Initially '$'
global function setnumberpunct(integer pPeriod, integer pComma, integer
pMoney)
    sequence lOldValues

    lOldValues = {vPeriod, vComma, vMoney}

    if pPeriod >= 0 and pPeriod <= 255 then
        vPeriod = pPeriod
    end if

    if pComma >= 0 and pComma <= 255 then
        vComma = pComma
    end if

    if pMoney >= 0 and pMoney <= 255 then
        vMoney = pMoney
    end if

    if (vPeriod = vComma)
    or (vPeriod = vMoney)
    or (vComma  = vMoney)
    then
        -- Duplicate chars used so revert.
        vPeriod = lOldValues[1]
        vComma  = lOldValues[2]
        vMoney  = lOldValues[3]
    else
        vLegalChars = "0123456789abcdef-+" & vPeriod & vComma
    end if

    return lOldValues
end function

---
-- Converts a text sequence to a number (atom).
--  Leading and trailing spaces are ignored.
--  If the text is enclosed in parenthesis, a negative number is returned.
--  If the number begins with ...
--    [Money Symbol]  : base is assumed as 10
--    #  : base is assumed as 16 (Hexadecimal)
--    0x : base is assumed as 16 (Hexadecimal)
--    0b : base is assumed as 2 (Binary)
--    0d : base is assumed as 16 (Decimal)
--    0O : base is assumed as 8 (Octal)
--    x' : base is assumed as 16 (Hexadecimal) and final is dropped
--    b' : base is assumed as 2 (Binary) and final is dropped
--    d' : base is assumed as 16 (Decimal) and final is dropped
--    O' : base is assumed as 8 (Octal) and final is dropped
--
-- The text can have a single embedded '-' or '+'
-- Base 10 text can have commas
--
-- It returns an atom which is the converted number
--    (or as much as could be converted)
--
-- If an error was detected in the source string, such as a subsequence,
--           a non-integer atom, or a character other than 0-9 a-f ".,+-",
--           or a digit not in the current number base, then the function
-- isconverr() returns the position in the string that
-- contains the offending element.
--
-- Examples:
--       sequence rc
--       rc = seqtonumber(" $2,150.95")
--       --> rc = 2150.95   isconverr() --> 0
--
--       rc = seqtonumber("1234-")
--       --> rc = -1234  isconverr() --> 0
--
--       rc = seqtonumber("0xff73")
--       --> rc = 65395  isconverr() --> 0
--
--       rc = seqtonumber("b'001101'")
--       --> rc = 13  isconverr() --> 0
--
--       rc = seqtonumber("12 Cats")
--       --> rc = 12  isconverr() --> 3
--
--       rc = seqtonumber("12.3.3 Cats")
--       --> rc = 12.3  isconverr() --> 5
--

---- Valid "number" modifier prefixes.
constant kNumStarts =
        {
            {"0X", 256, 16, 0},
            {"0O", 256,  8, 0},
            {"0B",  11,  2, 0},
            {"0D",  13, 10, 0},
            {"X'", 256, 16, 1},
            {"D'", 256, 10, 1},
            {"O'", 256,  8, 1},
            {"B'", 256,  2, 1}
        }
integer NumConvErr NumConvErr = -1

global function isconverr()
    return NumConvErr
end function

global function seqtonumber(sequence pData)
    atom lResult

    integer lDotFound, lSign, lPos, lOk, lChar, lValue
    atom  lRHS, lLHS, lRHSdepth, lFullValue
    integer lBase, lUsingRHS, lCommas
    integer lStart, lEnd, lConvStarted, lTrailingSign
    sequence lTemp


    NumConvErr = 0
    lResult = 0
    lDotFound = 0
    lSign = 0
    lUsingRHS = 0
    lConvStarted = 0
    lTrailingSign = 0

    lRHS = 0
    lRHSdepth = 1
    lLHS = 0
    lBase = vBase

    -- Disregard trailing and leading blanks
    lStart = length(pData) + 1
    for i = 1 to length(pData) do
        if pData[i] != ' ' then
            lStart  = i
            exit
        end if
    end for
    lEnd = 0
    for i = length(pData) to 1 by -1 do
        if pData[i] != ' ' then
            lEnd  = i
            exit
        end if
    end for

    -- Look for parenthesized numbers.
    if equal('(', pData[lStart]) and equal(')', pData[lEnd]) then
        lStart += 1
        lEnd -= 1
        lSign = -1
    end if

    -- Examine for special start codes.
    if   lEnd - lStart >= 0
    then
        if equal(vMoney, pData[lStart]) then
            -- Cater for spaces between the $ and first digit.
            for i = lStart+1 to lEnd do
                if pData[i] != ' ' then
                    lStart  = i
                    exit
                end if
            end for
            lBase = 10
        elsif equal('#', pData[lStart]) then
            lBase = 16
            lStart += 1
        elsif lStart != length(pData) then
            lTemp = upper(pData[lStart .. lStart + 1])
            for i = 1 to length(kNumStarts) do
                if equal(lTemp, kNumStarts[i][1]) then
                    if lBase < kNumStarts[i][2] then
                        lBase = kNumStarts[i][3]
                        lStart += length(kNumStarts[i][1])
                        lEnd -= kNumStarts[i][4]
                        exit
                    end if
                end if
            end for
        end if
    end if

    -- Only base-10 can have commas
    if lBase != 10 then
        lCommas = 0
    else
        lCommas = 1
    end if

    -- Start parsing the string.
    lPos = lStart
    lOk = 1
    while 1 do
        -- No more characters?
        if lPos > lEnd then
            exit
        end if

        -- Check for embedded sequences
        if sequence(pData[lPos]) then
            lOk = 0
            exit
        end if

        -- Check for non-integer elements.
        if not integer(pData[lPos]) then
            lOk = 0
            exit
        end if

        -- Pluck out the next char to examine.
        lChar = lower(pData[lPos])

        -- Is it legal char.?
        lValue = find(lChar, vLegalChars) - 1
        if lValue < 0 then
            lOk = 0
            exit
        end if

        -- Values below the base are usable digits.
        if lValue < lBase then
            -- This prevents embedded signs.
            if lTrailingSign = 1 then
                lOk = 0
                exit
            end if

            -- Signal that conversion is underway.
            lConvStarted = 1

            -- Am I doing the Left or Right side of the "decimal" symbol?
            if lUsingRHS then
                -- Right side.
                -- Accume that value so far.
                lRHS = (lRHS * lBase) + lValue
                -- Calculate the RHS divisor
                lRHSdepth *= lBase
            else
                -- Left side.
                -- Accume the value so far.
                lLHS = (lLHS * lBase) + lValue
            end if
        else
            -- Start checking for special symbols.

            -- A negative sign?
            if lChar = '-' then
                -- If I haven't found one yet then mark this a -ve number
                -- and if conversion had started, its a trailing sign.
                if lSign = 0 then
                    lSign = -1
                    lTrailingSign = lConvStarted
                else
                    -- Duplicate sign sybol detected.
                    lOk = 0
                    exit
                end if
            -- A positive sign?
            elsif lChar = '+' then
                -- If I haven't found one yet then mark this a +ve number
                -- and if conversion had started, its a trailing sign.
                if lSign = 0 then
                    lSign = 1
                    lTrailingSign = lConvStarted
                else
                    -- Duplicate sign sybol detected.
                    lOk = 0
                    exit
                end if
            -- A decimal position symbol?
            elsif lChar = vPeriod then
                -- If I haven't found one yet then mark that I now have
                -- and start processing the right hand side.
                if lDotFound = 0 then
                    lDotFound = 1
                    lUsingRHS = 1
                else
                    -- A duplicate decimal symbol found.
                    lOk = 0
                    exit
                end if
            -- A digit separator?
            elsif lChar = vComma then
                -- If this base is not allowed digit separators, flag an
error.
                if lCommas = 0 then
                    lOk = 0
                    exit
                end if
            else
            -- Must be a non-legal character for current number base.
                lOk = 0
                exit
            end if
        end if

        -- Bump to next input character.
        lPos += 1
    end while

    -- If no sign symbols used, assume a positive number.
    if lSign = 0 then
        lSign = 1
    end if

    -- Calculate the actual value represented by the string.
    lFullValue = lSign * (lLHS + (lRHS / lRHSdepth))

    if not lOk then
        NumConvErr = lPos
    else
        NumConvErr = 0
    end if

    return lFullValue
end function

----------------------------

------
Derek Parnell
Melbourne, Australia
"To finish a job quickly, go slower."

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu