views:

78

answers:

4

I am very confused about how decimal numbers work in perl. I'm having trouble multiplying an int with a double. Here's what I have:

sub timeEstimate(){
$number = shift;
print "Number: $number\n";
$stuff = sprintf("%d", $number * $number * $number) * .2045;
print "stuff: $stuff\n";
$totalDownloads = $stuff + ($number * $number) + $number;
print "totalDownloads: $totalDownloads\n";
$secondPerFile = .4464;
print "secondPerFile: $secondPerFile\n";
$totalSeconds = ($totalDownloads * $secondPerFile);
print "totalSeconds: $totalSeconds\n";
$totalHours = ($totalSeconds / 3600);
print "totalHours: $totalHours\n";
return $totalHours;
}

But no matter what I try, even sprintf, I still can't get $stuff to be anything but 0. Could someone explain how the system works?

UPDATE-Solved: Due to stupid self-inflicted mistake. I had

use integer; 

in the code. headdesk

A: 
perl -e '$var = "0.123"; print sprintf("%02.5f\n", $var);'
0.12300

sprintf works fine with decimal numbers.

Edit:

Looks like you have also not used "use strict", which will help with any variable name typos. And i'd drop the () from the function declaration.

halkeye
I'm not having a problem with sprintf, I'm having a problem multiplying an int with a double. How do I do that?
Sho Minamimoto
@Sho Minamimoto: You multiply them with the * operator. IIRC, Perl doesn't have distinct numeric types, so there's no difference between an int and a double anyway.
David Thornley
Absolutely no difference? Because this is what I put: my $stuff = ($number * $number * $number) * .2045; and no matter what, $stuff is always equal to 0. ($number = 138)
Sho Minamimoto
@Sho Minamimoto: No difference. If you think that some sort of int/double difference is giving you problems in Perl, you're wrong. Any problems you have are not due to some issue that simply does not exist. In this case, it looks to me like `$number` was coming out as 0 because of the prototype, and that's your problem.
David Thornley
A: 

The code in your question has a semantic error. You should start it with

sub timeEstimate {  # no parens!

Are you forgetting to pass an argument to timeEstimate? Calling it as

timeEstimate 3;

gives the following output:

Number: 3
stuff: 5.5215
totalDownloads: 17.5215
secondPerFile: 0.4464
totalSeconds: 7.8215976
totalHours: 0.002172666
Greg Bacon
I'm calling it as $estimate = timeEstimate($size);Size is of course an int. And no matter what, it won't multiply the $number with that decimal.
Sho Minamimoto
A: 

Your problem is with the subroutine prototype -- you have an empty argument list but you're calling it with one argument.

Make it timeEstimate($) and you'll be fine. Then call "timeEstimate( 10 )" or whatever.

However I don't see how you even could run it without getting an error message.

c-urchin
Or better, don't use prototypes at all. In Perl, they fall into the category of "avoid until you know exactly why you need one".
Ether
+2  A: 

Once variables have been declared and the prototype removed from the function, your code seems to work:

use warnings;
use strict;

sub timeEstimate {
    my $number = shift;
    print "Number: $number\n";

    my $stuff = sprintf("%d", $number * $number * $number) * .2045;
    print "stuff: $stuff\n";

    my $totalDownloads = $stuff + ($number * $number) + $number;
    print "totalDownloads: $totalDownloads\n";

    my $secondPerFile = .4464;
    print "secondPerFile: $secondPerFile\n";

    my $totalSeconds = ($totalDownloads * $secondPerFile);
    print "totalSeconds: $totalSeconds\n";

    my $totalHours = ($totalSeconds / 3600);
    print "totalHours: $totalHours\n";
    return $totalHours;
}

timeEstimate 10;


Number: 10
stuff: 204.5
totalDownloads: 314.5
secondPerFile: 0.4464
totalSeconds: 140.3928
totalHours: 0.038998

In Perl functions, you always need to declare your variables with the my keyword (which allocates a lexically scoped variable) otherwise you will run into problems. Using use warnings; use strict; at the top of every program will keep you from forgetting, and will also provide many useful diagnostic messages.

The () prototype you have on the timeEstimate function is in error. It specifies that the timeEstimate function does not accept any arguments. Do not use Perl's function prototypes until you know exactly why you need to be using them.

Lastly, your use of sprintf is not needed. The line can be rewritten as:

my $stuff = 0.2045 * ($number ** 3);
Eric Strom
putting use strict; breaks my code... it dumps pages of crap about compilation errors. Wtf?
Sho Minamimoto
If your code is breaking under `strict` then chances are it has more problems than you know. Perl gives you many many ways to shoot yourself in the foot, up to and including pulling the trigger for you. `strict` is your safety net.
Eric Strom
Ok, now I've gone through and added 'my' to all my declarations, and I have warnings and strict on, but it's still giving me $stuff = 0. Mind you, I'm using a passed int as big as 127 or 138. Does perl have a problem dealing with a number as big as 138^3?
Sho Minamimoto
*Always* `use strict; use warnings;`. Always always always. There is never a need to deviate from this. (Sometimes you may need to temporarily disable a check *for one particular line of code*, but you should always understand exactly why you need to do this, and understand the drawbacks and limitations.)
Ether
@Sho => Perl doesn't have any sort of limit that you will be hitting in your code. (the limit of a number in Perl is the maximum size of a double on your platform). Perl also doesn't make a meaningful distinction between integers and floats for normal math. The two can be mixed without worry. The problem in your code is not with the math, but with missing variable declarations and incorrect function prototypes. You should remove all prototypes from your functions unless you know exactly why you need them. Chances are your errors are starting there.
Eric Strom
Actually, I just found use integer; at the top...But thanks for the explanation, that's what I wanted anyway.
Sho Minamimoto
@Ether: Also, and this isn't on the same level of importance, avoid function prototypes. They rarely help, and sometimes bite.
David Thornley