[Omaha.pm] Jay on IRC - print "$j " . int($j) . "\n"; # prints '14 13'

Jay Hannah jay at jays.net
Fri Oct 27 04:21:57 PDT 2006


For the archive, here's me on IRC a year ago or something. #perl is  
explaining perl and C black magic to me. There may or may not have  
been a bug in my Perl / kernel installation...

That was one of those mind blowing mornings where perl was not doing  
what I thought it should.  :)

j




#perl: +ascent_ +phuct +nocarrier +Skunk
*** End of /NAMES list.
*** Channel Mode is +spmtnl 123 *** Channel created at Monday, April  
16, 2001 5:48:56 AM
*** #perl You're not channel operator
*** Mode change "+v dferret" on #perl by Roderick
   dferret: my $j = (log 16384) / (log 2);
   dferret: print "$j " . int($j) . "\n";  # prints '14 13'
   dferret: Whats up with that? If $j is really 13.9999999999 why  
doesn't it print like that?
   dferret: (Linux 2.4.17)
    joe321: number_format($num, 2) == 12.34
    joe321: oops
    joe321: wrong language
    Kyriel: Beat me, daddy, eight-to-the-bar.
     Somni: perldoc -q decimal
     Somni: and follow the perlop reference
   dferret: I understand perldoc -q decimal. I don't understand why,  
if $j is really 13.99999999999 when I do a print $j it prints "14"...?
   dferret: If 'print $j' spit out 13.999999999999 I'd understand the  
problem.
*** taer (~tdunn at adsl-64-175-241-190.dsl.sntc01.pacbell.net) has  
joined channel #perl
*** Mode change "+v taer" on #perl by Roderick
     Somni: dferret: because floating point numbers are imprecise
   corwin_: [corwin at gw3 corwin]$ perl -le '$a = 13.99999999999; print  
$a'
   corwin_: 13.99999999999
    cfedde: remember all that limit stuff from calculus?  Well here  
it is again.
   Psyche^: they are precise... they're just not real numbers in the  
mathematical sense :-)
     Somni: the floating point value doesn't match the reality of the  
calculation; I would call that imprecise
   dferret: So you're saying that print might round a floating point  
up to 14? I thought print would always print 13.9999999999 as  
13.9999999999999, but I'm getting "14". I didn't think print would  
round.
     wadi3: how can I store the output of an sql statement in a $var?
    cfedde: wadi3: read about the DBI
   corwin_: beat me to it cfedde :-)
   Psyche^: floats are computer numbers and not mathematical numbers.  
you just expect too much from the poor things...
    cfedde: dferret: perl -le 'my $j = (log 16384) / (log 2); print  
"$j " . int($j)'
    cfedde: 14 14
*** Signoff: taer (Ping timeout: 378 seconds)
   dferret: I get '14 13' w/ Perl 5.8.0 on Linux 2.4.17
    cfedde: perl -v -> This is perl, v5.8.2 built for i386-freebsd
   dferret: Did I compile in the PRINT_FUNCTION_ROUNDS var? :p
     Somni: I get 14 14 with 5.8.0 on Linux 2.4.22
     Somni: dferret: it has nothing to do with print
   Psyche^: 14 14 5.8.2 2.6.0t11
   dferret: Must be a Linux bug. I'll email Linus. -grin-
*** Signoff: wadi3 ()
   dferret: What do you mean it's not print? The only reason int($j)  
would spit out 13 on my box is that $j is really 13.9999999999 but  
print $j is showing 14 -- meaning that print is rounding, right? - 
ponder-
     Somni: dferret: print is how you happen to be stringifying the  
number
     Somni: it has to do with how computers deal with floating point  
values
   dferret: I expected it to stringify 13.999999999 as 13.9999999999,  
not 14. I didn't know print would stringify upwards.
     Somni: how have you determined 13.9999999999 is the correct  
result?  even bc says it's supposed to be 14.00000000000000000014
    cfedde: dferret: there has to be something odd in the way that  
your math libraries are working.  Is your perl using some wierd  
version of log?
   dferret: I figured it must be slightly < 14 because int($j) spits  
out 13. int() rounds down, right?
     Somni: my TI-85 says it's 14
*** alkatraz (~ugh at ip68-9-124-191.ri.ri.cox.net) has joined channel  
#perl
*** Mode change "+v alkatraz" on #perl by Roderick
   dferret: How would I know what log perl is using?
     Somni: int rounds towards zero, effectively; it just strips off  
the integral part
    cfedde: s/ingegral/fractional/
   dferret: Right, do that's how I "deetermined" that it must be  
13.9999999999 not 14.000000000001
     Somni: integral, and returns it
*** Signoff: morfic (Quit: Leaving)
   dferret: s/do/so/
*** morfic (~U3N at cs662583-130.satx.rr.com) has joined channel #perl
*** Mode change "+v morfic" on #perl by Roderick
     Somni: dferret: what does bc or dc say?
   dferret: ...err... command line? Can't find those commands.  
(Excuse my ignorance.)
     Somni: echo "l(16384) / l(2)" | bc -l
   dferret: bc: command not found
     Somni: write a C program then
    cfedde: what kind of flakey linux distribution does not have bc?
     Somni: #include <math.h>\n#include <stdio.h>\nint main ()  
{ printf("%.20f\n", log(16384) / log(2)); return 1; }
     Somni: or something to that effect
*** Signoff: zerologic (Read error: Connection reset by peer)
   dferret: jhannah at hannibal:~/cgi-bin$ ./j
   dferret: 14.00000000000000000000
     Somni: is perl linked to the same libm your new program is?
*** Signoff: epyon_II (Ping timeout: 624 seconds)
*** tdunn (~tdunn at adsl-64-175-241-190.dsl.sntc01.pacbell.net) has  
joined channel #perl
*** Mode change "+v tdunn" on #perl by Roderick
     Somni: ldd j; ldd `which perl`
   dferret: ldd shows both my perl and my new C prog are using the  
exact same /lib/lib* files...
     Somni: do you have Devel::Peek installed?
*** zubs (~zubz at user-0ccemmv.cable.mindspring.com) has joined channel  
#perl
*** Mode change "+v zubs" on #perl by Roderick
   dferret: yes...
      zubs: if i want to find any of these characters \/:*?"<>| what  
would the regex code look like?
     Somni: perl -MDevel::Peek -wle '$j = log(16384) / log(2); Dump 
($j);'
     Somni: zubs: perldoc perlre, perldoc perlretut, perldoc perlrequick
*** Signoff: morfic (Quit: Leaving)
     Somni: dferret: paste the result to knowpaced
knowpaced: I'm a pastebot!  Paste stuff at http://pastebot.nd.edu/perl
      zubs: thx
   dferret: SV = PVNV(0x8165510) at 0x814bfb0
   dferret:   REFCNT = 1
   dferret:   FLAGS = (NOK,pIOK,pNOK)
   dferret:   IV = 13
   dferret:   NV = 14
   dferret:   PV = 0
     Somni: ugh
   dferret: What does that mean? -laugh-
     dngor: dferret: Bzt.
   corwin_: dferret: knowpaced
knowpaced: I'm a pastebot!  Paste stuff at http://pastebot.nd.edu/perl
*** Signoff: tdunn (Ping timeout: 240 seconds)
*** Signoff: joe321 ()
*** Mode change "+l 121" on #perl by Roderick
     Somni: dferret: at most it's proof your problem has nothing to  
do with print
     Somni: that perl is shoving two different values in the IV and  
NV elements is a little odd
   dferret: -ponder-  We're way over my head here.
            dferret grins
*** morfic (~U3N at cs662583-130.satx.rr.com) has joined channel #perl
*** Mode change "+v morfic" on #perl by Roderick
   Psyche^: i get  FLAGS = (NOK,pNOK) NV = 14
*** tdunn (~tdunn at adsl-64-175-241-190.dsl.sntc01.pacbell.net) has  
joined channel #perl
   Psyche^: why is IV set at all?
*** Mode change "+v tdunn" on #perl by Roderick
     Somni: it's set on mine too
     Somni: but to 14
   Psyche^: your perl sucks, mine is better. bwuahahaha
*** Signoff: tdunn (Read error: Operation timed out)
     Somni: heh
   dferret: 5.8.0 problem?
     Somni: dferret: nope
     Somni: probably some combination of compile flags
     Somni: paste perl -V output to knowpaced, that's PASTE TO KNOWPACED
knowpaced: I'm a pastebot!  Paste stuff at http://pastebot.nd.edu/perl
knowpaced: "dferret" at 68.13.20.113 pasted "perl -V" at http:// 
pastebot.nd.edu:80/304
     Somni: Psyche^: do you have uselongdouble defined in your perl -V?
   Psyche^: uselongdouble=undef
     Somni: dferret: that may be your culprit, though it's hard to say
     Somni: you could try recompiling without it, upgrade to 5.8.2,  
or just stick it out
     Somni: I may compile a perl with it enabled to see if that's it  
when I get back
   cwilbur: evening all.
*** zubs has left channel #perl
   dferret: I was justs surprised as all sheeot that it happened. I  
thought print always printed whatever.... I guess something wacky  
must be happening internally. Anyhoozit, I'll probaby just use  
sprintf to turn 13.999999999999 into 14?
     Somni: the value -is- 14, something is being miscalculated  
internally
   cwilbur: this sounds like a floating point rounding problem.
     Somni: it did initially
   cwilbur: though I have only skimmed about a page of scrollback.
     Somni: but the IV for the value is 13, when every calculation  
I've done makes it out as 14
     Somni: and several versions of perl agree
     Somni: anyways, afk, dinner
*** Signoff: Somni (dinner)
   cwilbur: right, but if the floating-point math comes out to  
13.999999, wouldn't the IV most appropriately be 13?
   dferret: I don't know anything about IV, so w/ Somni gone talking  
to me will be like talking to a wall. -grin-
    cfedde: It appears that different implementations of the log  
function over estemate or underestemate.
   dferret: Ya, my mystery though was that print is printing 14, not  
13.99999999999 like I'd expect.
   dferret: perl -le 'my $j = (log 16384) / (log 2); print "$j " . int 
($j)'
   dferret: On my system that prints "14 13". Everyone else gets "14  
14".
    cfedde: yes.  I was the silly person that pasted the command line  
yuo just pasted back
   dferret: My explanation is that $j is 13.9999999999999 so int  
takes it to 13, which I expect. I didn't expect print to "round" to  
14 though...?  (I'm just recapping for cwilbur.)
   cwilbur: well, the next question is, what's different about your  
system?
   cwilbur: (both my systems say 14 14.)
   dferret: Somni's theory was that I have USE_LONG_DOUBLE  compiled  
into perl.
   cwilbur: that could be.
   cwilbur: neither of my systems have USE_LONG_DOUBLE compiled in.
    cfedde: dferret: is this a perl that came with your distribution?  
or did you compile it yourself?
   dferret: ?  I'm on perl 5.8.0. Is this something I should take the  
time to actually formalize for Perl 5 porters?
   dferret: This isn't my server -- I don't know what distro it is or  
how Perl got on there. I can call the guy.
    cfedde: don't worry about it.
   cwilbur: it's probably worth documenting.
   dferret: Is it a bug? I expected print to print 13.9999999999, but  
maybe that was a bad assumption?
   dferret: Maybe I should just learn that print might "round" too?  
Or would that be a lesson that no one should learn?
    cfedde: perl -le 'print 13.9999999999999, " ", 13.99999999999999'
    cfedde: 13.9999999999999 14
    cfedde: isn't that odd?
   Psyche^: no, 14 is even.
   cwilbur: print probably tries to do the right thing.
   dferret: I get 13.9999999999999 13.99999999999999
   cwilbur: having taken rounding error into account.
    cfedde: Keep extending the 9s on the second one till you get 14
   dferret: (Because of my USE_LONG_DOUBLE?)
   Psyche^: same as cfedde here
    cfedde: it's the default number template for printf
    cfedde: because of USE_LONG_DOUBLE, yes
    cfedde: s/f$//;
*** elkane (kane at phree.ne.client2.attbi.com) has joined channel #perl
*** Mode change "+v elkane" on #perl by Roderick
   dferret: perl -le 'print 13.9999999999999999, " ",  
13.99999999999999999'
   dferret: 13.9999999999999999 14
   dferret: Your cutoff is 14 9s, mine is 17?
    cfedde: I guess that you win!
*** peanuter (worldapart at host-64-179-13-126.syr.choiceone.net) has  
joined channel #perl
   cwilbur: well, you're using long doubles.
*** Mode change "+v peanuter" on #perl by Roderick
   dferret: So my log is rounding to a precision my print can't handle?
    cfedde: dferret: no that's not it.
*** Signoff: jaredy (Quit: leaving)
    cfedde: read the description of $# in perldoc perlvar
*** jaredy (~jaredy at dorms-pppoe-1-74-225.pittsburgh.resnet.pitt.edu)  
has joined channel #perl
*** Mode change "+v jaredy" on #perl by Roderick
   dferret: perldoc says: Use of $# is deprecated.  -grin-
    cfedde: but it gives you a hint about what is happening.
   dferret: perl -e 'print $#'  doesn't print anything
    cfedde: perl's print is written in terms of printf.  If your perl  
defines USE_LONG_DOUBLE then it changes the number of digits that  
print prints before rounding.
   dferret: hmm... Why would you ever want print to round? Wouldn't  
you want it to always print the full float? Rounding is for printf,  
isn't it?
    cfedde: perl -e 'printf "%5.2f %5.2f\n", 13.99, 13.999'
    cfedde: perl's print rounds by default.     cfedde: and  
apparently USE_LONG_DOUBLE controls some aspect of it.
     Leolo: purl, seen kismet
      purl: kismet was last seen on #perl 4 hours, 31 minutes and 3  
seconds ago, saying: Ok, IBMs little download dealio is.... weird  
[Wed Dec 10 19:33:59 2003]
*** Signoff: elkane ()
   dferret: Seems strange to me. I would think that print wouldn't  
round by default so it would be easy to see the whole float.
   dferret: perl -le 'my $j = (log 16384) / (log 2); printf("% 
0.200f", $j)'
   dferret:  
13.999999999999999999132638262011596452794037759304046630859375000000000 
000000000000000000000000000000000000000000000000000000000000000000000000 
00000000000000000000000000000000000000000000000000000000000
       arp: nice
    cfedde: Where do you suppose accuracy of that number begins to  
falter?
   dferret: So what's the easy way to print a whole float? If I can't  
trust print to do it because print is rounding? I can't printf 'cause  
I don't know where the float actually ends?
   dferret: "whole float" as in to whatever precision $j is actually  
living in memory.
    cfedde: remember that even double floats are approximations of  
the actual value with some posible error.
   dferret: Sure. I understand.   In the case above I would expect  
print to print  
"13.999999999999999999132638262011596452794037759304046630859375". If  
I wanted it rounded I'd printf it myself. You said print rounds by  
default -- is there a way to disable that?
    cfedde: nope
   whorian: hi
*** yoo (~momo at 200.86.20.13) has joined channel #perl
*** Mode change "+v yoo" on #perl by Roderick
   dferret: weird.
    cfedde: and the the authors of perl are probably smarter than you  
about were the error begins.
   dferret: I'm sure they are. Listening to a Damian lecture gives me  
a headache due to excessive brilliance. -grin- *** yoo has left  
channel #perl
    cfedde: the number of decemal places that print uses is usualy  
too many for most practical purposes anyway.
    cfedde: perldoc perlnumber
     dngor: EYE-NUMBINGLY BRIGHT
   whorian: WHAT
   dferret: The lesson I learned tonight is: Just because print spits  
out a round number doesn't mean that your scalar has a round number  
in it. It may be rounded. I didn't know that. I thought print would  
always print all the precision in memory.    cfedde: usualy when you  
are working with floating point numbers you want to see if your  
result is within some error brackets.
   dferret: s/It may be rounded/print may be rounding your scalar for  
you/
   dferret: error brackets?
    cfedde: s/ may be/is/
   dferret: ya.
    cfedde: usualy you want to test that your result is within say  
10e-3 or 10e-6 of what you expect
    cfedde: digits beyond the expected accuracy are just noise.
     Leolo: there's a var that controls print's precision, iirc
   dferret: Ya, but I don't know what I'm expecting, I'm just  
expecting something rediculously close to an integer, so I'll just  
use sprintf("%.0f", $j) to force it into an int for me... I didn't  
know I had to be paranoid in that way.    cfedde: Leolo: we found  
$#.  but it appears to be depreciated.
     Leolo: $#      The output format for printed numbers.
     Leolo: right
            dferret grins
     Leolo: dferret : why not use int() to force it into an int?
    cfedde: dferret: you need to decide what "rediculously close"  
means in your context.
    cfedde: Leolo: read the backlog
            dferret laughs
   dferret: I could paste the backlog into channel? -mischevious grin-
     Leolo: the back-log can't be nearly as boring as the proposal  
I'm writting
   dferret: I hope it's a bikeshed. I like bikesheds.






More information about the Omaha-pm mailing list