Fun with numbers - dammit, but I want a cast!

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Graham Nicholls

    Fun with numbers - dammit, but I want a cast!

    Hi.

    I'm having some fun with numbers. I've extraced an image sizes from a jpeg
    file

    img_x,img_y=ima ge.getsize()

    then I'm trying to use those sizes to scale the image, but because python
    has decided that they are integers, I keep getting division by zero errors

    eg
    xscale=xframe/img_x

    where xframe will be say 300, and img_x will be 1800
    xscale has the value 0.

    I've tried doing img_x=1.0 to force it to be a float, but I'm getting a bit
    frustrated as it seems to make no difference - once image.getsize returns
    the (integer) value of the x size, it simply converts back to an int. I've
    tried this at the command line, and it seems to confirm that behaviour -
    eg:
    graham@rocklap: ~/work/hsb/pdflive> python
    Python 2.3b1 (#3, Jun 17 2003, 23:06:11)
    [GCC 3.3 20030226 (prerelease) (SuSE Linux)] on linux2
    Type "help", "copyright" , "credits" or "license" for more information.[color=blue][color=green][color=darkred]
    >>> x=1.0
    >>> xf=1.0
    >>> scale=1.0
    >>> x=1800
    >>> xf=300
    >>> scale=xf/x
    >>> scale[/color][/color][/color]
    0[color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]




    Heres the relevant code in full:

    img_x=1.0
    img_y=1.0
    img_x,img_y=ima ge.getsize()
    except "Not_JPEG":
    if warn:
    print ("WARNING: Image file %s is not a jpeg file" % fname)
    sys.exit(OPEN_E RR)
    # How many pixels per mm do we have
    # On a4 paper, using pdfrw ? Docs seem to suggest between 60-160
    # which seems a lot.

    xscale=1.0
    yscale=1.0
    scale=1.0
    xscale=1/(xframe/img_x)
    yscale=1/(yframe/img_y)
    #import pdb
    #pdb.set_trace( )
    print ("xscale=%f,ysc ale=%f" %(xscale,yscale ))
    scale=min(xscal e,yscale) * 100
    print ("xframe=%d,yfr ame=%d, x=%d,y=%d scale=%f\n" %(xframe, yframe,
    img_x, img_y, scale))

    I'd really appreciate some help, thanks!
    Graham
    --
    Graham Nicholls
    Rock Computer Consultancy

  • Charl P. Botha

    #2
    Re: Fun with numbers - dammit, but I want a cast!

    In article <3f378fac$0$107 78$afc38c87@aut h.uk.news.easyn et.net>,
    Graham Nicholls wrote:[color=blue]
    > then I'm trying to use those sizes to scale the image, but because python
    > has decided that they are integers, I keep getting division by zero errors
    >
    > eg
    > xscale=xframe/img_x
    >
    > where xframe will be say 300, and img_x will be 1800
    > xscale has the value 0.[/color]

    Have you tried doing it this way:
    xscale = xframe / float(img_x)

    --
    charl p. botha http://cpbotha.net/ http://visualisation.tudelft.nl/

    Comment

    • Duncan Booth

      #3
      Re: Fun with numbers - dammit, but I want a cast!

      Graham Nicholls <graham@rockcon s.co.uk> wrote in
      news:3f378fac$0 $10778$afc38c87 @auth.uk.news.e asynet.net:
      [color=blue]
      > eg
      > xscale=xframe/img_x
      >
      > where xframe will be say 300, and img_x will be 1800
      > xscale has the value 0.
      >
      > I've tried doing img_x=1.0 to force it to be a float, but I'm getting
      > a bit frustrated as it seems to make no difference - once
      > image.getsize returns the (integer) value of the x size, it simply
      > converts back to an int.[/color]

      Variables don't have types in Python, objects have types. Assigning a float
      object to a variable doesn't have any effect on the type of the next
      object assigned to the same variable.

      To get the behaviour you want either convert at least one of your values to
      a float:

      xscale = float(xframe)/img_x

      or add the following 'magic' line to the top of your sourcefile:

      from __future__ import division

      If your file has that line at the top, division will behave more the way
      you expect: casting to float automatically whenever you divide integers.

      --
      Duncan Booth duncan@rcp.co.u k
      int month(char *p){return(1248 64/((p[0]+p[1]-p[2]&0x1f)+1)%12 )["\5\x8\3"
      "\6\7\xb\1\x9\x a\2\0\4"];} // Who said my code was obscure?

      Comment

      • Richard Brodie

        #4
        Re: Fun with numbers - dammit, but I want a cast!


        "Graham Nicholls" <graham@rockcon s.co.uk> wrote in message
        news:3f378fac$0 $10778$afc38c87 @auth.uk.news.e asynet.net...
        [color=blue]
        > I've tried doing img_x=1.0 to force it to be a float, but I'm getting a bit
        > frustrated as it seems to make no difference - once image.getsize returns
        > the (integer) value of the x size, it simply converts back to an int.[/color]

        Yes. Types are properties of values, not names. There is no implied
        declaration: you can assign a float to img_x then later an int, string,
        function or whatever.

        To get floating point division you can use a cast like syntax, by using
        the builtin float() function.
        [color=blue][color=green][color=darkred]
        >>> 1 / 2[/color][/color][/color]
        0[color=blue][color=green][color=darkred]
        >>> float (1) / float(2)[/color][/color][/color]
        0.5

        In future versions of Python, / will become a floating point division operator.
        // will be used for truncating division. For compatibility, you need to
        explicitly enable the new behaviour at present, either with a from __future__
        or a -Q option. These activate Guido's famous time machine, which add
        new features to Python before you ask for them.
        [color=blue][color=green][color=darkred]
        >>> from __future__ import division
        >>> 1 / 2[/color][/color][/color]
        0.5[color=blue][color=green][color=darkred]
        >>> 1 // 2[/color][/color][/color]
        0

        U:\>python -Qwarn
        ActivePython 2.2.2 Build 224 (ActiveState Corp.) based on
        Python 2.2.2 (#37, Nov 26 2002, 10:24:37) [MSC 32 bit (Intel)] on win32
        Type "help", "copyright" , "credits" or "license" for more information.[color=blue][color=green][color=darkred]
        >>> 1/2[/color][/color][/color]
        __main__:1: DeprecationWarn ing: classic int division
        0


        Comment

        • Torsten Marek

          #5
          Re: Fun with numbers - dammit, but I want a cast!

          Graham Nicholls schrieb:[color=blue]
          > Hi.
          >
          > I'm having some fun with numbers. I've extraced an image sizes from a jpeg
          > file
          >
          > img_x,img_y=ima ge.getsize()
          >
          > then I'm trying to use those sizes to scale the image, but because python
          > has decided that they are integers, I keep getting division by zero errors
          >
          > eg
          > xscale=xframe/img_x
          >
          > where xframe will be say 300, and img_x will be 1800
          > xscale has the value 0.
          >
          > I've tried doing img_x=1.0 to force it to be a float, but I'm getting a bit
          > frustrated as it seems to make no difference - once image.getsize returns
          > the (integer) value of the x size, it simply converts back to an int. I've
          > tried this at the command line, and it seems to confirm that behaviour -
          > eg:
          > graham@rocklap: ~/work/hsb/pdflive> python
          > Python 2.3b1 (#3, Jun 17 2003, 23:06:11)
          > [GCC 3.3 20030226 (prerelease) (SuSE Linux)] on linux2
          > Type "help", "copyright" , "credits" or "license" for more information.
          >[color=green][color=darkred]
          >>>>x=1.0
          >>>>xf=1.0
          >>>>scale=1.0
          >>>>x=1800
          >>>>xf=300
          >>>>scale=xf/x
          >>>>scale[/color][/color]
          >
          > 0
          >
          >
          >
          >
          >
          > Heres the relevant code in full:
          >
          > img_x=1.0
          > img_y=1.0
          > img_x,img_y=ima ge.getsize()
          > except "Not_JPEG":
          > if warn:
          > print ("WARNING: Image file %s is not a jpeg file" % fname)
          > sys.exit(OPEN_E RR)
          > # How many pixels per mm do we have
          > # On a4 paper, using pdfrw ? Docs seem to suggest between 60-160
          > # which seems a lot.
          >
          > xscale=1.0
          > yscale=1.0
          > scale=1.0
          > xscale=1/(xframe/img_x)
          > yscale=1/(yframe/img_y)
          > #import pdb
          > #pdb.set_trace( )
          > print ("xscale=%f,ysc ale=%f" %(xscale,yscale ))
          > scale=min(xscal e,yscale) * 100
          > print ("xframe=%d,yfr ame=%d, x=%d,y=%d scale=%f\n" %(xframe, yframe,
          > img_x, img_y, scale))
          >
          > I'd really appreciate some help, thanks!
          > Graham[/color]
          The type of a variable does not depend on the type it was initialized with.
          You could do
          t = 1
          t = 1.1
          t = "1"
          t = [1,]
          and the type changes each time. There is no concept of "int xscale" what
          you might have in mind.
          You just should convert the integer into a float with
          xscale=1/(xframe/float(img_x)).


          greetings
          Torsten

          Comment

          • Istvan Albert

            #6
            Re: Fun with numbers - dammit, but I want a cast!

            Graham Nicholls wrote:
            [color=blue][color=green]
            >>Have you tried doing it this way:
            >>xscale = xframe / float(img_x)[/color]
            >
            >
            > Thats what I wanted to do, but was sure I'd read that python didn't have
            > casts, and that _looks_ like a cast to me![/color]

            You can also force floating point math by muliplying with 1.0
            before the division:

            xscale = 1.0 * xframe/img_x

            Istvan.

            Comment

            • Alex Martelli

              #7
              Re: Fun with numbers - dammit, but I want a cast!

              Graham Nicholls wrote:
              ...[color=blue][color=green]
              >> xscale = xframe / float(img_x)[/color]
              >
              > Thats what I wanted to do, but was sure I'd read that python didn't have
              > casts, and that _looks_ like a cast to me![/color]

              Well, Python surely has the ability to create new objects, and the most
              typical way to do that is to call a type, possibly passing it, as the
              call's arguments, the value[s] that direct the new object's creation.


              So, for example, if you have a string S and want to create a list L
              whose items are the string's characters, you typically code:

              L = list(S)


              Similarly, if you have a number N and want to create a float F whose
              value is the floating-point equivalent of N's value, you code:

              F = float(N)


              Whether these are "casts" is, I guess, a pretty moot issue. Me, I'd
              call them "type calls" (or "explicit constructor calls" if I were in a C++
              mood:-), reserving the terminology "cast" for the C/Java notation:

              (sometype)somev alue

              or the C++ notations of forms such as:

              static_cast<som etype>(somevalu e)

              But, of course (in C++), explicitly calling a costructor of (e.g.) float,
              with an integer argument; or statically casting an int to float; or even
              using the old C-ish "prepended type in parenthesis" notation; have much
              the same effect in most contexts. As long as you're quite clear that
              what you're actually doing is "create a new value of a specified type
              by calling the type with suitable argument[s]", rather than (the typical
              idea of "cast") "reinterpre ting an existing value AS IF it was of some
              other type rather than of the type it actually is", it may not be a
              problem if you like to call the operation "a cast".


              Alex

              Comment

              • Graham Nicholls

                #8
                Re: Fun with numbers - dammit, but I want a cast!

                Istvan Albert wrote:
                [color=blue]
                > Graham Nicholls wrote:
                >[color=green][color=darkred]
                >>>Have you tried doing it this way:
                >>>xscale = xframe / float(img_x)[/color]
                >>
                >>
                >> Thats what I wanted to do, but was sure I'd read that python didn't have
                >> casts, and that _looks_ like a cast to me![/color]
                >
                > You can also force floating point math by muliplying with 1.0
                > before the division:
                >
                > xscale = 1.0 * xframe/img_x
                >
                > Istvan.[/color]
                Thanks everybody! I'm now sorted with numbers. At least 2.0+2.0 now equals
                about 4.0, anyway.
                Graham
                --
                Graham Nicholls
                Rock Computer Consultancy

                Comment

                • Erik Max Francis

                  #9
                  Re: Fun with numbers - dammit, but I want a cast!

                  Graham Nicholls wrote:
                  [color=blue]
                  > Thats what I wanted to do, but was sure I'd read that python didn't
                  > have
                  > casts, and that _looks_ like a cast to me![/color]

                  It's a function call, not a conversion. Even in C++, conversion by
                  constructor is not considered a cast. A cast would be:

                  xframe/static_cast<flo at>(image_x)

                  and there is no analogous structure to this in Python.

                  --
                  Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                  __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
                  / \ Nobody can reach me, nobody can touch me; it's a wonderful feeling.
                  \__/ Aaliyah

                  Comment

                  • Erik Max Francis

                    #10
                    Re: Fun with numbers - dammit, but I want a cast!

                    Terry Reedy wrote:
                    [color=blue]
                    > No, quite different. A C cast (at least usually) recasts a block of
                    > bits in a new role without changing the bits. Type constructors
                    > (unless redundant as in int(1)) return a different object with a
                    > different set of bits.[/color]

                    Well, the issue is that, in C, a cast can mean a lot of different
                    things. That's why, in C++, casts are separated into template like
                    syntaxes depending on their purpose. The unsafe form of C cast is a
                    reinterpret_cas t in C++, and sometimes a const_cast (if you actually
                    cast away constness of a truly const object and then attempt to mutate
                    it). The other two -- static_cast and dynamic_cast -- are "safe" in the
                    sense of being well-defined when the compiler accepts them, and merely
                    invoke a well-defined conversion and do a runtime type cast,
                    respectively.

                    --
                    Erik Max Francis && max@alcyone.com && http://www.alcyone.com/max/
                    __ San Jose, CA, USA && 37 20 N 121 53 W && &tSftDotIotE
                    / \ Nobody can reach me, nobody can touch me; it's a wonderful feeling.
                    \__/ Aaliyah

                    Comment

                    • Istvan Albert

                      #11
                      Re: Fun with numbers - dammit, but I want a cast!

                      Andrew Koenig wrote:[color=blue]
                      >
                      > Python is going to change its behavior so that division always
                      > returns a floating-point value. This statement causes that new
                      > behavior to occur now.[/color]

                      Will there be a keyword/function for integer division after that?

                      Not that my opinion has any weight in this matter, but I got used
                      to integer division as default behavior after all C, and java
                      work that way too, it is not like it is a pythonic oddity.

                      Once it gets implemented then there will be numerous questions about
                      doing integer division.

                      Istvan.



                      Comment

                      • Hannu Kankaanpää

                        #12
                        Re: Fun with numbers - dammit, but I want a cast!

                        Andrew Koenig <ark@acm.org> wrote in message news:<yu99fzk87 15z.fsf@tinker. research.att.co m>...[color=blue]
                        > 2) At the beginning of your source file, execute:
                        >
                        > from __future__ import division
                        >
                        > Python is going to change its behavior so that division always
                        > returns a floating-point value. This statement causes that new
                        > behavior to occur now.[/color]

                        By the way, do you know a reason why after doing

                        from __future__ import division

                        this still happens:
                        [color=blue][color=green][color=darkred]
                        >>> 3.0 // 2[/color][/color][/color]
                        1.0

                        Wouldn't it be more convenient to present the resulting whole
                        number as an integer now, since division operation on integers
                        works correctly? At least IMO the operation
                        [color=blue][color=green][color=darkred]
                        >>> 3.0 // 2[/color][/color][/color]
                        1

                        would be more convenient and natural, and floor division could then be
                        used to get array indices for example:

                        print arr[position // scale]

                        Not that I -really- care either way, since casting division result
                        to int isn't verbose either. Just curious, if you or anyone
                        knows the reason for new floor div working this way.

                        Comment

                        • Carl Banks

                          #13
                          Re: Fun with numbers - dammit, but I want a cast!

                          Terry Reedy wrote:[color=blue]
                          > No, quite different. A C cast (at least usually) recasts a block of
                          > bits in a new role without changing the bits.[/color]

                          Certainly not. Most type casts actually change bits. For example,
                          supposing floats and longs are both 32 bits, the expression (float)1L
                          will *not* return the floating point number with the same bit pattern
                          as 1L. It returns 1.0.

                          Usually, the only casts that preserve the bit pattern are integer to
                          pointer casts, and the C standard doesn't even guarantee that (unless
                          C 2000 changed it). In fact, the C standard says (or used to say)
                          that 0 must always cast to a null pointer, even if the system
                          represents integer 0 and null pointer with different bits, which does
                          (or used to) happen.


                          IMO, a type cast is just a fancy name for an operator that takes an
                          object and returns an object with the same "value" (whatever that
                          means) but a different type. In C, type casting happens to have a
                          funny syntax. In Python, it does not. If someone asked, "does Python
                          have type casting?", I would say yes, except there's no special syntax
                          for it. Rather, type casting is done by the calling type objects
                          themselves.



                          --
                          CARL BANKS
                          "You don't run Microsoft Windows. Microsoft Windows runs you."

                          Comment

                          • Carl Banks

                            #14
                            Re: Fun with numbers - dammit, but I want a cast!

                            Erik Max Francis wrote:[color=blue]
                            > Carl Banks wrote:
                            >[color=green]
                            >> Certainly not. Most type casts actually change bits.[/color]
                            >
                            > Some casts do. Some merely invoke conversions.
                            >[color=green]
                            >> For example,
                            >> supposing floats and longs are both 32 bits, the expression (float)1L
                            >> will *not* return the floating point number with the same bit pattern
                            >> as 1L. It returns 1.0.[/color]
                            >
                            > But the C++ equivalent, something like (float) 1, would _not_ return the
                            > floating point number with the same bit pattern as 1L either. It would
                            > simply invoke the conversion from int to float. What you're talking
                            > about would be something like *(float *) &i.[/color]


                            It seems you didn't read what I wrote carefully. I was talking about
                            C, not C++. Neither I nor the post I replied to mentioned C++ once.
                            I mentioned the C standard several times, never the C++ standard.

                            Type casts in C are as I described.



                            --
                            CARL BANKS
                            "You don't run Microsoft Windows. Microsoft Windows runs you."

                            Comment

                            • Bengt Richter

                              #15
                              Re: Fun with numbers - dammit, but I want a cast!

                              On Mon, 11 Aug 2003 23:46:38 GMT, Carl Banks <imbosol@aerojo ckey.com> wrote:
                              [color=blue]
                              >Terry Reedy wrote:[color=green]
                              >> No, quite different. A C cast (at least usually) recasts a block of
                              >> bits in a new role without changing the bits.[/color]
                              >
                              >Certainly not. Most type casts actually change bits. For example,
                              >supposing floats and longs are both 32 bits, the expression (float)1L
                              >will *not* return the floating point number with the same bit pattern
                              >as 1L. It returns 1.0.
                              >
                              >Usually, the only casts that preserve the bit pattern are integer to
                              >pointer casts, and the C standard doesn't even guarantee that (unless
                              >C 2000 changed it). In fact, the C standard says (or used to say)
                              >that 0 must always cast to a null pointer, even if the system
                              >represents integer 0 and null pointer with different bits, which does
                              >(or used to) happen.
                              >
                              >
                              >IMO, a type cast is just a fancy name for an operator that takes an
                              >object and returns an object with the same "value" (whatever that
                              >means) but a different type. In C, type casting happens to have a
                              >funny syntax. In Python, it does not. If someone asked, "does Python
                              >have type casting?", I would say yes, except there's no special syntax
                              >for it. Rather, type casting is done by the calling type objects
                              >themselves.
                              >[/color]

                              Well, there is one way to look at existing bits exactly as they are in
                              terms of an alternate type representation. The easy way is to do reinterpret cast
                              on a pointer to change a pointer to the old type into a pointer to a new type,
                              without changing location. E.g., how else to print out the bit representation
                              of something? E.g., here's a hack to see floats and doubles as little-ending python strings:

                              ====< castf.c >============== =============== =========
                              #include <stdio.h>
                              #include <stdlib.h>

                              int main(int argc, char *argv[]){
                              float f4;
                              double f8;
                              int i;
                              if(argc<2){ printf("Usage: castf <floating point number for atof>\n"); return 0;}
                              f8 = atof(argv[1]); f4=f8;
                              printf("\"");
                              for(i=0; i<sizeof(f4); ++i){ printf("\\x%02x ",((unsigne d char *)(&f4))[i]);};
                              printf("\"\n");
                              printf("\"");
                              for(i=0; i<sizeof(f8); ++i){ printf("\\x%02x ",((unsigne d char *)(&f8))[i]);};
                              printf("\"\n");
                              return 0;
                              }
                              =============== =============== =============== ========
                              [18:04] C:\pywk\clp>cas tf
                              Usage: castf <floating point number for atof>

                              [18:04] C:\pywk\clp>cas tf 1.625
                              "\x00\x00\xd0\x 3f"
                              "\x00\x00\x00\x 00\x00\x00\xfa\ x3f"

                              [18:04] C:\pywk\clp>cas tf -1.625
                              "\x00\x00\xd0\x bf"
                              "\x00\x00\x00\x 00\x00\x00\xfa\ xbf"

                              [18:04] C:\pywk\clp>cas tf 0
                              "\x00\x00\x00\x 00"
                              "\x00\x00\x00\x 00\x00\x00\x00\ x00"

                              [18:04] C:\pywk\clp>cas tf 1
                              "\x00\x00\x80\x 3f"
                              "\x00\x00\x00\x 00\x00\x00\xf0\ x3f"

                              [18:04] C:\pywk\clp>cas tf -1
                              "\x00\x00\x80\x bf"
                              "\x00\x00\x00\x 00\x00\x00\xf0\ xbf"

                              Actually, it's a little confusing to look at numbers in that order, especially
                              since the hex for the bits in the bytes is big-end-on-the-left ;-)

                              2**54-1 (naturally I used python to get the number ;-)
                              [18:12] C:\pywk\clp>cas tf 180143985094819 83
                              "\x00\x00\x80\x 5a"
                              "\xff\xff\xff\x ff\xff\xff\x4f\ x43"

                              2**53-1
                              [18:12] C:\pywk\clp>cas tf 900719925474099 1
                              "\x00\x00\x00\x 5a"
                              "\xff\xff\xff\x ff\xff\xff\x3f\ x43"

                              2**52-2**12
                              [18:12] C:\pywk\clp>cas tf 900719925473689 6
                              "\x00\x00\x00\x 5a"
                              "\x00\xf0\xff\x ff\xff\xff\x3f\ x43"
                              ^^ ^-bits 8-11 (the f is bits 12-15)
                              ^^-bits 0-7

                              Of course, the cleaner way would have been to factor that instead of cutting and pasting:
                              Some architectures might not like addressing arbitrary bytes, but we'll leave that as exercise
                              material ;-)

                              ====< castf.c >============== =============== =========
                              #include <stdio.h>
                              #include <stdlib.h>

                              void prnch(void *pthing, int n){
                              int i;
                              printf("\"");
                              for(i=0; i<n; ++i){ printf("\\x%02x ",((unsigne d char *)(pthing))[i]);};
                              printf("\"\n");
                              }

                              int main(int argc, char *argv[]){
                              float f4; double f8;
                              if(argc<2){ printf("Usage: castf <floating point number for atof>\n"); return 0;}
                              f8 = atof(argv[1]); f4=f8;
                              prnch(&f4, sizeof(f4));
                              prnch(&f8, sizeof(f8));
                              return 0;
                              }
                              =============== =============== ============
                              Regards,
                              Bengt Richter

                              Comment

                              Working...