Announcement

Collapse
No announcement yet.

Problems converting quad to variant

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problems converting quad to variant


    There seems to be a problem converting large quads to variants or vice versa:

    Code:
    local q as quad
    local q1 as quad
    local q2 as quad
    local v as variant
    local d$
    
    
    q = 3372036854775807 '16 decimal places
    q1 = val("3372036854775807")
    v = q
    q2 = VARIANT#(v)
    if VARIANT#(v) = q then
      d$ = " equal"
    else
      d$ = " not equal"
    end if
    msgbox str$(q, 18) + $crlf + str$(q1, 18) + $crlf + str$(VARIANT#(v),18) + $crlf + str$(q2, 18) + $crlf + d$
    
    q = 23372036854775807 '17 decimal places
    q1 = val("23372036854775807")
    v = q
    q2 = VARIANT#(v)
    if VARIANT#(v) = q then
      d$ = " equal"
    else
      d$ = " not equal"
    end if
    msgbox str$(q, 18) + $crlf + str$(q1, 18) + $crlf + str$(VARIANT#(v),18) + $crlf + str$(q2, 18) + $crlf + d$
    
    q = 223372036854775807
    q1 = val("223372036854775807")
    v = q
    q2 = VARIANT#(v)
    if VARIANT#(v) = q then
      d$ = " equal"
    else
      d$ = " not equal"
    end if
    msgbox str$(q, 18) + $crlf + str$(q1, 18) + $crlf + str$(VARIANT#(v),18) + $crlf + str$(q2, 18) + $crlf + d$
    
    q = 446744073709551615
    q1 = val("446744073709551615")
    v = q
    q2 = VARIANT#(v)
    if VARIANT#(v) = q then
      d$ = " equal"
    else
      d$ = " not equal"
    end if
    msgbox str$(q, 18) + $crlf + str$(q1, 18) + $crlf + str$(VARIANT#(v),18) + $crlf + str$(q2, 18) + $crlf + d$
    The result of such a conversion is off by one, if the quad has more than 16 decimal places

    ???

    JK

  • #2
    It's only off by one becuase of rounding
    q = 23372036854775808 returns the desired 23372036854775808
    q = 23372036854775806 is off by two. It also returns 23372036854775808
    (23372036854775805 and 23372036854775804 both return 23372036854775804)

    The reason is because VariantVT(v) = 5 ( Double) even though the original value was a Quad.

    It seems that PB is not honouring declared variable or constant types.
    It converts integers larger than a Long to VariantType Double and smaller integers to Long
    (It seems as though Long and Double are the only two types it creates - Singles are converted to Doubles)

    A few examples:
    v2 = 23372036854775807&& also gives VARIANTVT (v) = 5
    and
    q=1
    v = q ; VARIANTVT(v) returns a 5 (Double)
    but
    v = 1 ; VARIANTVT(v) returns a 3 (Long)
    as does v=1&&
    also
    v=1.0 : VARIANTVT(v) returns 5 (Double)

    Comment


    • #3
      I've added a post in the Documentation area: https://forum.powerbasic.com/forum/u...pes#post817101

      Comment


      • #4
        Yes Stuart,

        i have seen that (VARIANTVT (v) = 5), but this is not how i would expect it be (i´m not an expert in variants) ... a feature, a limitation or a bug ?

        Comment


        • #5
          Originally posted by Juergen Kuehlwein View Post
          Yes Stuart,

          i have seen that (VARIANTVT (v) = 5), but this is not how i would expect it be (i´m not an expert in variants) ... a feature, a limitation or a bug ?
          It's definitiely a feature, but it's also a limitation
          It's not a bug since it is apparently performing as designed.

          Note that EXT are converted to Doubles as well so there can be a major loss of precision when using variants.


          Comment


          • #6
            "Note that EXT are converted to Doubles as well so there can be a major loss of precision when using variants."

            Interesting, since - "... In PowerBASIC, all floating point calculations are performed in extended precision for maximum accuracy. ..."

            Just an observation; though it seems odd to throw away precision that would be used during calculation.

            Cheerrs,
            Dale

            Comment


            • #7
              You should try it with A) quad-typed ('&&') numeric literals and B) explicit assignment of datatypes for the variants ('LET variantvar = 12345&& AS QUAD')

              Failing all that, there is a variant data type not supported by PowerBASIC, the "DECIMAL" but that is stored only as a character base 10 zoned decimal so arithmetic could be tricky.

              BUT... yes of course I have supplied starter code for you...

              Here in the source code forum you can see how to make and store variants not natively supported by PB:Create VT_DATE variant Datatype 9-14-09

              (And this may be useful, too: Get VARIANTVT literal)

              And on my web site here's a hint for basic arithmetic working with large display (character) numerics..http://talsystems.com/tsihome_html/downloads/Factor.zip


              Michael Mattias
              Tal Systems (retired)
              Port Washington WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                Hmm, I see in your doc note, Stuart, you say..

                Regardless of the variable type ( x AS ... ) or constant suffix (123&& etc):
                And I see Post number two this thread you tried the explicitly typed QUAD ("&&") numeric literal.

                But I don't see where you tried the inline variant datatype assignment ( LET v = 12345&& AS QUAD)


                FROM PB Help under LET:
                LET VrntVar= expression [AS vartype]

                The numeric or string expression is evaluated, and the result is stored in the variant variable. PowerBASIC will choose an appropriate numeric or string data type to use. However, you can specify a preferred format by adding an optional AS vartype clause. This can be BYTE, WORD, DWORD, INTEGER, LONG, QUAD, SINGLE, DOUBLE, CURRENCY, or WSTRING. Strings in a variant are always stored in wide Unicode, regardless of whether you add AS WSTRING or not. PowerBASIC handles the conversion automatically, if it is needed.
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  Thanks Michael,

                  testing your proposal:

                  Code:
                  local q as quad
                  local q1 as quad
                  local q2 as quad
                  local v as variant
                  local d$
                  
                  
                  q = 446744073709551615
                  q1 = val("446744073709551615")
                  'v = 446744073709551615&& 'doesn´t work
                  ' v = 446744073709551615 as quad 'works !!!
                  ' v = q 'doesn´t work
                  ' v = q&& 'doesn´t work
                  v = q as quad 'works !!!
                  q2 = VARIANT#(v)
                  if VARIANT#(v) = q then
                    d$ = " equal"
                  else
                    d$ = " not equal"
                  end if
                  msgbox str$(q, 18) + $crlf + str$(q1, 18) + $crlf + str$(VARIANT#(v),18) + $crlf + str$(q2, 18) + $crlf + d$
                  you can see: "AS QUAD" works, a type specifier ("&&") doesn´t. So if you want PB to convert a numeric variable into a variant, you shouldn´t let PB guess, what you want, but you should tell PB by adding an "AS <Data Type>" specification. Variantvt now returns 20 for "AS QUAD", which is expected.

                  Again ... after all those years i learn something new everyday


                  JK

                  Comment


                  • #10
                    Type specifier makes the literal (446744073709551615) a QUAD.
                    AS QUAD makes the variant variable v a quad.
                    If the literal is less than a max LONG I'd suggest both.

                    Cheers,
                    Dale

                    Comment


                    • #11
                      you shouldn´t let PB guess, what you want, but you should tell PB...
                      And you wonder why I don't like defaults?.
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        I've updated the documentation post. Important point:

                        Using "AS EXT" in the assignement causes a compile error. It appears that there is no way to store an EXT in a variant.
                        v = 1.2345 AS EXT ' returns Error 482 - Data type mismatch

                        Comment


                        • #13
                          Originally posted by Michael Mattias View Post
                          FROM PB Help under LET:
                          Since I have not used LET in the last 30 years or so, I've never paid much attention to that part of Help
                          I see under "LET statement (with Variants)" ["Not under LET statement":]

                          LET VrntVar= expression [AS vartype]
                          The numeric or string expression is evaluated
                          ,...

                          PowerBASIC will choose an appropriate numeric or string data type to use

                          I would have assumed (maybe naively) that the "approrpiate" type would be the defined type where the "expression" is a simple assignment of a typed constant or variable.
                          "Choosing" an appropriate type should only be required where the "expression" was something which actually needed to be "evaluated"

                          This can be BYTE, WORD, DWORD, INTEGER, LONG, QUAD, SINGLE, DOUBLE, CURRENCY, or WSTRING.
                          So that confirms that you can't store an EXT in a variant.

                          Comment


                          • #14
                            I would have assumed....
                            1. And you wonder why I don't like defaults?

                            (Didn't I just say that?)

                            2. Amazing what you can learn when you .
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              I wonder if PowerBASIC EXTENDED is designed to be IEEE '754' 80 bit extended precision? Does not say in PB Win 10 help.

                              Enquring Minds Want to Know!

                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                              • #16
                                I've updated the documentation post
                                Good for you, sir.

                                One of the reasons I "re-activated" a couple years ago was the sheer quantity of bad info available here .. info which may have been corrected "somewhere else" but remained nonetheless.

                                WAY better this way!
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17

                                  According to Wikipedia ( yes, I know )
                                  The IEEE 754 floating-point standard recommends that implementations provide extended precision formats. The standard specifies the minimum requirements for an extended format but does not specify an encoding. The encoding is the implementor's choice.

                                  I know you don't like assumptions but:
                                  SInce "Extended-precision numbers are the basis of computation in PowerBASIC". I assume that it is in the x86 extended precision format
                                  "the x86 extended precision format is an 80-bit format first implemented in the Intel 8087 math coprocessor and is supported by all processors that are based on the x86 design that incorporate a floating-point unit"

                                  Comment


                                  • #18
                                    I know you don't like assumptions but: .... I assume that it is in the x86 extended precision format
                                    Just like you might assume that 'LET variantVar = (QuadDatatypeVariable | NumericLiteral&&) ' will assign the variant as a QUAD type?

                                    But FWIW, I agree with you because I believe PowerBASIC would have used a standard rather than developing its own 10-byte floating point type.

                                    Someone with another language compiler which supports IEEE '754' extended precision as well as a PB compiler could check it pretty easily.
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment

                                    Working...
                                    X