Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, I think I'm running into a bug in perl, or some syntax I'm not aware of. Can someone confirm either for me? I'm running this with perl 5.6.1, here's the test case: print(time, "\n"); print(time * 1000, "\n"); The output of this is: 1001696383 969003032 The first one is correct, but the second one is obviously not the result of multiplying the first by 1000. thanks, Abi

Replies are listed 'Best First'.
Re: time() function
by tachyon (Chancellor) on Sep 28, 2001 at 21:28 UTC

    This is because time is using a 32 bit integer and you are getting an overflow truncation like you do in say C. Here is a demo of what happens:

    $time = time(); $odd = time * 1000; print "$time|$odd\n"; print "2**31 is ", 2**31, "\n"; $time1000 = $time *1000; $time1000 %= 2**31; print "Here is our number: $time1000\n"; print "End of *nix epoch is at: ", scalar gmtime (2**31-1)

    The maximum integer value that time will hold is 2**31 or 2147483648. As $time1000 is much bigger than this we get overflow tructation. We simulate this with modulus % and lo and behold produce the same number.

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      So, I understand this is true. I'm O.K. with overflows. I can handle overflows. But why does
      $var = time * 1000;
      overflow and
      $var = time; $var *= 1000;
      not overflow?

      I believe that on my system (Win2k, perl 5.6.1) integers are 32 bit, just like returned by time() I verified this with print ($var&(~0)) which gives me (2**32)-1.

      Does perl automatically decide (not) to use BigInts? Any ideas?

      Ira,

      "So... What do all these little arrows mean?"
      ~unknown

        time() is a Perl function, implemented in C with 32 bit (long int) math relevant to the unix epoch.

        A perl scalar is an interesting beast (also implemented in C) that can hold a string or a number or a reference so is not directly comparable to a short, int, long, float, double, char in C. It is in fact a struct. Have a look at this code and perlman:perlguts. On the Win95 box in front of me Perl will represent up to 2**49 (562,949,953,421,312) as an integer before resorting to scientific notation.

        for ( 0..64 ) { $var = 2**$_; print "Perl can do 2**$_ : $var\n"; }

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: time() function
by ducky (Scribe) on Sep 28, 2001 at 21:28 UTC

    Maybe the perl hackers (as apposed to the Perl hackers) can correct me: your typical integer (x86 arch) is going to be 32bits. time returns an integer, and 1000 is an integer, so perl's going to return the results as an integer too. But the largest number a signed integer can express is roughly 2 billion. Time just spilled over into the 1 billions fairly recently. So the result is overflowing, giving you the "inaccurate" answer.

    See how Math::BigInt works out for you.

    -Ducky

      That's right. You can use a special build option (-Duse64bit, IIRC) on some platforms(including Linux) to get 64-bit ints, which I think go into the trillions without overflowing.

      =cut
      --Brent Dax
      Perl 6 Configure pumpking
      There is no sig.

Re: time() function
by dcd (Scribe) on Sep 29, 2001 at 02:19 UTC
    perl -e 'print(time, "\n"); print(time*1e3, "\n");' 1001715463 1001715463000
    Making one of the numbers look like a float fixes the problem.