I’m Really Starting to Hate Computers

Free­dom is the right to say that two plus two makes four. If that is grant­ed, all else follows. 

—George Orwell, 1984

Yes­ter­day I spend the lat­ter part of the day in the stu­dio fin­ish­ing up a pen and ink draw­ing. Work­ing in pen and ink makes sense to me. There’s a lot I don’t under­stand, but every thing I learn makes me bet­ter at what I do. The world makes sense when I’m putting ink on paper. If I want to bet­ter under­stand the shape of a shoul­der, I can look at peo­ple’s shoul­ders and read anato­my books and prac­tice draw­ing shoul­ders. Whether my marks on paper resem­ble a shoul­der depends on a con­sis­tent set of rules. Yes, dif­fer­ent peo­ple per­ceive things dif­fer­ent­ly, but even so what I do at the draw­ing table devel­ops a con­sis­tent visu­al lan­guage. Some things I do bet­ter than oth­ers, but I can keep work­ing on my short­com­ings and improv­ing my abil­i­ty to con­vey the sense of objects and/or ideas I wish oth­ers to see when they look at the paper.

Today I’m in the office earn­ing mon­ey by work­ing on some Perl code.

Per­haps this is just proof that I am inca­pable of under­stand­ing the com­plex lan­guages and log­ic of machines, but after the bet­ter part of my life pro­vid­ing pro­gram­mat­ic instruc­tions to com­put­ers and more than a dozen years specif­i­cal­ly work­ing with Perl, some­times I feel like the com­put­er and I aren’t speak­ing the same language.

Some­times I bang my head against a sil­ly mis­take I’ve over­looked, and after a few min­utes or hours or days final­ly see what I’ve missed and get a good laugh at myself. Oth­er times, like tonight, I sim­pli­fy my prob­lem down to the most basic parts, con­firm that I’m doing what I think I’m doing, and stare dumb­found­ed at the machine that tells me that two plus two is not a num­ber. And I just don’t get it.

For­give the fol­low­ing code. It’s part of a test I wrote to see why a method I wrote was­n’t return­ing the val­ues I thought it should. Don’t wor­ry, I’ll explain.

        my $retail = 0;
        foreach my $rateid ( @{$self->{RATES}} ) { 
            my $quant = $self->{TICKETQUANTITIES}->{$rateid};
            my $retail_rate = $self->{'TOUR'}->{'RATE'}{$rateid}{'retail_rate'};
            my $coupon = $self->{COUPONAMOUNT};
            $test .= "\n<!-- Retail: $retail_rate Quantity: $quant Discount: $coupon -->\n";
            # now perform maths to prove these things are numbers 
            $retail_rate += 1.03;
            $coupon += 1;
            $quant +=1;
            # are they really numbers?
            $test .= "\n<!-- Retail: $retail_rate Quantity: $quant Discount: $coupon -->\n";
            # Okay, now add them up!
            my $discounted_rate = ($retail_rate - $coupon);
            $retail += ($quant * ($retail_rate - $coupon));
            $test .= "\n<!-- Discounted rate: $discounted_rate Retail total: $retail -->\n";
        }

Okay, it’s sim­pli­fied for test­ing but here are the basics. In this code, any­thing that starts with $self-> is get­ting some kind of infor­ma­tion out of the data­base. In par­tic­u­lar, I’m bring­ing up prices and check­ing for dis­counts and quan­ti­ties for a par­tic­u­lar order. So this part:

        my $retail = 0;
        foreach my $rateid ( @{$self->{RATES}} ) { 

estab­lish­es $retail as a place to store the total price for the entire order, then cre­ates a loop where we look at all of the rates for this par­tic­u­lar order, one at a time, and we iden­ti­fy the rate that we’re look­ing at with $rateid. With me so far?

The first thing I do for each rate is get the par­tic­u­lar infor­ma­tion about the rate.

            my $quant = $self->{TICKETQUANTITIES}->{$rateid};
            my $retail_rate = $self->{'TOUR'}->{'RATE'}{$rateid}{'retail_rate'};
            my $coupon = $self->{COUPONAMOUNT};

It’s sort of inscrutable, but trust me. It pulls num­bers out of the data­base. They could even be the wrong num­bers; it does­n’t mat­ter. The very next thing I do is check to see what the num­bers are. Since what I’m test­ing is part of a web appli­ca­tion, I hide my tests in HTML com­ments that I can see when I look at the source of the web page. This is done by dump­ing the com­ments into a vari­able that I echo to the page lat­er on. Just under­stand that what­ev­er I add to the vari­able $test I can see after I run the code.

            $test .= "\n<!-- Retail: $retail_rate Quantity: $quant Discount: $coupon -->\n";

Now, I want to make sure that these val­ues real­ly are num­bers. So I per­form some math on them, by adding num­bers to them and send­ing the results to the $test vari­able where I can look at them after the addition.

            # now perform maths to prove these things are numbers 
            $retail_rate += 1.03;
            $coupon += 1;
            $quant += 1;
            # are they really numbers?
            $test .= "\n<!-- Retail: $retail_rate Quantity: $quant Discount: $coupon -->\n";

Now is the frus­trat­ing part. I want to get every­thing added up so that I know how much the cus­tomer is going to pay. I’m sure that every­one whose cred­it card will be charged would like to pay the cor­rect amount.

            # Okay, now add them up!
            my $discounted_rate = ($retail_rate - $coupon);
            $retail += ($quant * ($retail_rate - $coupon) );

And then we show the val­ues of $discounted_rate (a new vari­able cre­at­ed just so that we can look at the adjust­ed rate) and $retail

            $test .= "\n<!-- Discounted rate: $discounted_rate Retail total: $retail -->\n";
        }

That last brack­et clos­es the loop, say­ing that that’s the end of the code used to look at the rates.

If this has made any sense so far, you might guess like I did, that what I’ll see from this code will look some­thing like this:

<!-- Retail: 109.98 Quantity: 2 Discount: 0 -->

<!-- Retail: 111.01 Quantity: 3 Discount: 1 -->

<!-- Discounted rate: 110.01 Retail total: 330.03 -->

<!-- Retail: 5.00 Quantity: 0 Discount: 0 -->

<!-- Retail: 6.03 Quantity: 1 Discount: 1 -->

<!-- Discounted rate: 5.03 Retail total: 5.03 -->

Instead, what I see is the more perplexing:

<!-- Retail: 109.98 Quantity: 2 Discount: 0 -->

<!-- Retail: 111.01 Quantity: 3 Discount: 1 -->

<!-- Discounted rate: NaN Retail total: NaN -->

<!-- Retail: 5.00 Quantity: 0 Discount: 0 -->

<!-- Retail: 6.03 Quantity: 1 Discount: 1 -->

<!-- Discounted rate: NaN Retail total: NaN -->

NaN stands for «Not a Num­ber». It’s some­thing the com­put­er tells me when I try to do some sort of impos­si­ble math, like divi­sion by zero or tak­ing the square root of a neg­a­tive num­ber. But all I think I’ve done is a lit­tle addi­tion, sub­trac­tion, and mul­ti­pli­ca­tion. If any of the things I tried to add or mul­ti­ply were not num­bers, I’d get this result. «“Wis­con­sin” + 3» for exam­ple, might equal NaN. But every­thing I’ve been adding and sub­tract­ing and mul­ti­ply­ing are num­bers. I made sure that they were num­bers by adding to them and check­ing that the val­ues were correct.

So is there any won­der why I’d rather spend time in the stu­dio than in the office? It’s sim­ple: art makes log­i­cal sense. Com­put­ers don’t.

I look for­ward to being total­ly humil­i­at­ed by the obvi­ous answer that I’m miss­ing. When I find it, I will post it here just to embar­rass myself. Any­one read­ing this may feel free to point out what I’ve missed. Until then, I’m cur­rent­ly in my sev­enth hour of try­ing to deter­mine why the com­put­er is telling me that two plus two is not a number.

2 Replies to “I’m Really Starting to Hate Computers”

  1. A few more things that don’t make sense
    $discounted_rate ++; # this is a number
    $discounted_rate += 1; # this is NOT a num­ber (should be exact­ly the same as the pre­vi­ous line)
    $discounted_rate = $discounted_rate + 1; # this is also not a num­ber and should be the same as the above

  2. Now it makes sense
    OK, here’s what happened:

    Else­where in this mod­ule I need­ed to throw some big num­bers around, so I used a pack­age called Math::BigInt to get access to num­bers larg­er than those that Perl nor­mal­ly lets me work with. Because I’m lazy, I told Math::BigInt to take care of all my inte­gers in this par­tic­u­lar module.

    Math::BigInt is pret­ty mag­i­cal. It waits for any old inte­ger to be used in the mod­ule, then steals it away and cre­ates a blessed Big­Int object in its place. In most cas­es it appears iden­ti­cal, but it’s not. All my num­bers were no longer scalar val­ues but objects that returned scalar val­ues. This led to some sub­tle dif­fer­ences in the way my num­bers were handled.

    More on this in the Perl­Monks post.

    I’m still not sure exact­ly what’s going on inside Math::BigInt, but I think what’s hap­pen­ing is that it is inter­cept­ing a non-inte­ger num­ber when it isn’t sup­posed to, and, see­ing that it is not an inte­ger, reports it as not a num­ber. The fol­low­ing code repro­duces the problem:

    #!/usr/bin/perl
    
    use Math::BigInt ':constant';
    
    $discount = 15;
    $price = "109.98";
    
    print $discount * $price;
    
    exit();
    

    It prints «NaN» unless the sec­ond line is com­ment­ed out. I’m inclined to think this is a bug in Math::BigInt, but the behav­ior may be inten­tion­al. In any case, I moved the use state­ment to a place where it only affects a small chunk of code where it is need­ed and my prob­lems have gone away.

Leave a Reply