in reply to Integer vs Float during addition

To Zaxo & Halley
Actually, I already knew all that 0 vs 0.0, true vs false stuff. :-)
My query was that given $cost starts as a float and then sometimes has an integer added to it, why is the result integer, not float? I'm sure that in the background int is promoted to float for the actual calc, and given the tgt is already a float, I'd expect a float result?
Surely that's a reduction of the variable?
As implied above, this code I inherited(!) doesn't print the value, it's just used for a boolean test.
Cheers
Chris
I'm just trying to understand the internals a bit more.

Replies are listed 'Best First'.
Re^2: Integer vs Float during addition
by syphilis (Archbishop) on Jun 30, 2006 at 04:37 UTC
    I'm just trying to understand the internals a bit more

    It's often enlightening (and fun) to use Devel::Peek to get a glimpse of what the scalar actually looks like:
    use warnings; use Devel::Peek; $int = 17; #print "\$int: $int\n"; Dump($int); print "##############\n\n"; $double_1 = 1.23456789; #print "\$double_1: $double_1\n"; Dump($double_1); print "##############\n\n"; $double_2 = 1.0000; #print "\$double_2: $double_2\n"; Dump($double_2); print "##############\n\n"; $ul = 2 ** 31 + 16; # too big for an IV #print "\$ul: $ul\n"; Dump($ul); print "##############\n\n"; $double_3 = 2 ** 46 + 19; # too big for a UV or IV #print "\$double_3: $double_3\n"; Dump($double_3); print "##############\n\n"; $int += 0.0123; # $int no longer an IV #print "\$int: $int\n"; Dump($int); print "##############\n\n";
    Which outputs:
    D:\pscrpt>perl try.pl SV = IV(0x89c7cc) at 0x3f5d3c REFCNT = 1 FLAGS = (IOK,pIOK) IV = 17 ############## SV = NV(0x8afcb4) at 0x3f5d24 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 1.23456789 ############## SV = NV(0x8afcbc) at 0x8a3204 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 1 ############## SV = IV(0x89c7c8) at 0x8ba4d8 REFCNT = 1 FLAGS = (IOK,pIOK,IsUV) UV = 2147483664 ############## SV = NV(0x8afcc4) at 0x8a2fdc REFCNT = 1 FLAGS = (NOK,pNOK) NV = 70368744177683 ############## SV = PVNV(0x3f8714) at 0x3f5d3c REFCNT = 1 FLAGS = (NOK,pNOK) IV = 17 NV = 17.0123 PV = 0 ##############
    Note that $double_2 (assigned a value of 1.000) is an NV (perl's idea of a double) as you expected, but the actual value in the NV slot has been truncated to simply '1' ... when you 'print $double_2;', it's the value in the NV slot that gets printed.

    $ul is assigned a value that's too big to be a signed int, so it gets assigned to the UV slot, and the IsUV flag gets set. And $double_3 is assigned an integer value that can only fit into a double ... so, naturally, it has to be an NV.

    Note also that $int, which starts out as an IV, becomes an NV as soon as you add a float to it - and that the original IV value remains in the IV slot. It's the fact that the NOK and pNOK flags are set that determines that the NV value (rather than the value in the IV slot) will be displayed if you then 'print $int;'.

    Furthermore, if you enable those print statements that are currently commented out, you'll see that the various Dump() outputs change.

    Devel::Peek doesn't really explain anything, but it does let you see how the scalars are changing - and from that you can often come to a "good enough" understanding of what's happening. If you want a thorough understanding then you probably need to examine the perl source code.

    (And, of course, I always find that Devel::Peek throws up something unexpected - eg I don't know why doing '$int += 0.0123;' sets the PV slot to 0.)

    Cheers,
    Rob