Beginner: little rand() question in a long posting ...

M

Marek Stepanek

Hello happy Perlers,


a beginner has to struggle with many mysterious problems. One of these
problems is, to ask a question shortly, so excuse me for this long posting.

I have tried to put in a script a random number. I read the perlfaq4 ("How
do I get a random number between X and Y?") and made my first "random steps"
with this script, which is working fine:

#!/usr/bin/perl

# here a subroutine found in: % perldoc perlfaq4

my $random_number = random_int_in(50,120);

sub random_int_in ($$)
{
my($min, $max) = @_;
# Assumes that the two arguments are integers themselves!
return $min if $min == $max;
($min, $max) = ($max, $min) if $min > $max;
return $min + int rand(1 + $max - $min);
}

print "here it comes: my first random number, I hope: \n\t$random_number
!!\n\nWOW! It's workin :) \n\n";

my $random_number2 = random_int_in(1,7);
my $random_number3 = "1.$random_number2";

print "there is coming a second random Number! \n\t$random_number2\n\nWOW!
It's still workin :)\n\n";

print "there is coming a third random Number! \n\t$random_number3\n\nWOW!
It's still workin :)\n\n";

I am integrating it into my script, producing a LaTeX - file, but I get
mysterious error messages:

main::random_int_in() called too early to check prototype at ./calc_hours.pl
line 54.
Argument "185.88 / 1.8" isn't numeric in sprintf at ./calc_hours.pl line 63,
<IN> line 61 ...

This script is long, sorry:

#!/usr/bin/perl

use strict;
use warnings;

#### Files #################
my $in_file = 'calc_hours_in.tex';
open IN, "< $in_file" or die "Could not open your in_file: $!";
my $out_file = 'calc_hours.tex';
open OUT, "> $out_file" or die "Connot create your out_file: $!";
####END Files ##############

my $latex_head = <<"EOF";
\\documentclass[a4]{scrartcl}
\\usepackage[utf8]{inputenc}
\\usepackage{ltxtable}
\\clubpenalty = 10000
\\widowpenalty = 10000

\\begin{document}
Fahrer\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\hfill
{Monat}\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_
\\begin{longtable}[c]{| c | c | c | c | c | c | c | c |}
\\hline
\\multicolumn{8}{| c |}{\\textbf{Tageseinnahmen/Arbeitsnachweis}} \\\\
\\hline
& & & \\multicolumn{5}{ c |}{\\textbf{Arbeitszeit}} \\\\
\\hline
\\textbf{Datum} & \\textbf{Umsatz 7\\%} & \\textbf{Umsatz 16\\%} &
\\textbf{Beginn} & \\textbf{Pause} & \\textbf{Ende} & \\textbf{Stunden} &
\\textbf{Km-Gesamt} \\\\
\\hline
EOF

my $latex_foot = <<EOF;
\\end{longtable}
\\end{document}
EOF

print OUT "$latex_head";

####Variables###############
my $date1 = '';
my $date2 = '';
my @lines_in = '';
my @lines_out = '';
my $sum = 0;
my $sum_total = 0;
my $sum_total_sb = 0;
####End Variables###########

####Read in and work########
while ( <IN> ) {
/^(\w+, +[\d.]+)/ and $date1 = $1;
if (/^TOTAL/) { push @lines_in, "$date1\t$_"};
}
my $random_number = random_int_in(5,8);
foreach my $line (@lines_in) {
($sum) = $line =~ /([\d.]+)\s+$/;
($date2) = $line =~ /^(\w+, +[\d.]+)/;
$sum_total += $sum if $sum;
$sum *= 0.40 if $sum;
$sum_total_sb += $sum if $sum;
my $random_km = "1.$random_number";
my $km_tag = "$sum / $random_km" if $sum;
$km_tag = sprintf("%.2f", $km_tag) if $sum;
my $begin = 6;
my $end = $begin + 8;
my $hours = $end - $begin;
push (@lines_out,
"$date2\t&\t$sum\t&\tUmsatz16\t&\t$begin\t&\t$random_km\t&\t$end\t&\t$hours\
t&\t$km_tag\\\\\n" ) if $sum;
}
####END Read in and work####

####Output##################

print OUT "@lines_out";
print OUT "Gesamt:\t&\t$sum_total_sb\t&\t&\t&\t&\t&\t&\\\\\n";
print OUT $latex_foot;

####END Output##############

sub random_int_in ($$)
{
my($min, $max) = @_;
# Assumes that the two arguments are integers themselves!
return $min if $min == $max;
($min, $max) = ($max, $min) if $min > $max;
return $min + int rand(1 + $max - $min);
}

close OUT;
close IN;

The IN-File ( calc_hours_in.tex ) contains many lines, from which I read in
only the TOTALs and work on it ...

Son, 16.07.2006 37086.40 15445.00 808 19.50 3156.30
Mon, 17.07.2006 37667.00 15769.20 817 19.50 3621.00
TOTAL 580.60 324.20 9 0.00 464.70

Mon, 17.07.2006 37667.00 15769.20 817 19.50 3621.00
Die, 18.07.2006 37936.50 15929.60 823 19.50 3857.80
TOTAL 269.50 160.40 6 0.00 236.80
 
P

Paul Lalli

Marek said:
a beginner has to struggle with many mysterious problems. One of these
problems is, to ask a question shortly, so excuse me for this long posting.

I have tried to put in a script a random number. I read the perlfaq4 ("How
do I get a random number between X and Y?") and made my first "random steps"
with this script, which is working fine:

#!/usr/bin/perl
Always include the lines:
use strict;
use warnings;

right below the shebang
# here a subroutine found in: % perldoc perlfaq4

my $random_number = random_int_in(50,120);

sub random_int_in ($$)
{

I am integrating it into my script, producing a LaTeX - file, but I get
mysterious error messages:

Error messages in perl are not mysterious. They are very well
explained by reading:
perldoc perldiag

Even better, you can put the line:
use diagnostics;
at the top of your script, and cause Perl to look up the description of
the error messages for you.
main::random_int_in() called too early to check prototype at ./calc_hours.pl
line 54.

This means exactly what it says. Your subroutine has a prototype, but
you called the subroutine before you declared it. Hence the prototype
could not be checked. Define the subroutine first. Or at least
declare it first. See: perldoc perlsub

my $random_km = "1.$random_number";
my $km_tag = "$sum / $random_km" if $sum;
$km_tag = sprintf("%.2f", $km_tag) if $sum;

Argument "185.88 / 1.8" isn't numeric in sprintf at ./calc_hours.pl line 63,
<IN> line 61 ...

You assigned $km_tag to a string: "185.88 / 1.8". I assume you meant
to assign it to a numerical computation (ie, the result of 185.88
divided by 1.8). If that's the case, remove the quotes in the third
quoted line above:

my $km_tag = $sum / $random_km if $sum;
This script is long, sorry:

Don't be sorry... just don't do it. Post a short-but-complete script
that demonstrates your error. That should be one of your first steps
towards debugging a problem to begin with.

Paul Lalli
 
T

Ted Zlatanov

Argument "185.88 / 1.8" isn't numeric in sprintf at ./calc_hours.pl line 63,
<IN> line 61 ... ....
$sum_total += $sum if $sum;
$sum *= 0.40 if $sum;
$sum_total_sb += $sum if $sum;
my $random_km = "1.$random_number";
my $km_tag = "$sum / $random_km" if $sum;
$km_tag = sprintf("%.2f", $km_tag) if $sum;

Hi Marek,

I wanted to mention two things in addition to Paul Lalli's comments.

First, you have "STATEMENT if $sum" many times. Just use one if:

if ($sum)
{
a;
b;
c;
}

I also don't think you need to do it exactly this way - what will
happen if $sum is zero? I don't think any of the statements I quoted
need to be skipped, since the numbers won't change. Perhaps you want
"if (defined $sum)" instead, if $sum is undefined sometimes.

Second, you are generating $random_km with "1.NUMBER" and the random
number is between 5 and 8. You really want to use some math here; the
proper solution is (I think)

$random_km = 1.5 + rand(0.3); # random between 1.5 and 1.7999...

which will give you random numbers between 1.5 and 1.7999999... (but
never 1.8). I hope I understood what you are trying to do. The
function you have is fine, but may be overkill for your needs. If you
need the number to have only N digits of precision, use sprintf() as
you already use it for $km_tag to get 2 digits of floating point
precision.

Check out "perldoc -f rand" for more info.

Ted
 
M

Mumia W.

[...]
main::random_int_in() called too early to check prototype at ./calc_hours.pl
line 54.

Prototypes are not often used in Perl. My advice is to avoid
them, but if you use them, they must appear before the
function invokation, so this won't work right:

my $value = my_function(3,19);
sub my_function($$) {
...
}

But this will work right:

sub my_function($$); # <---- declares prototype
my $value = my_function(3,19);
sub my_function($$) {
...
}
Argument "185.88 / 1.8" isn't numeric in sprintf at ./calc_hours.pl line 63,
<IN> line 61 ...

This line,
my $km_tag = "$sum / $random_km" if $sum;

Does not perform a calculation because you assign a string to
$km_tag. Remove the quotes to allow Perl to perform a
calculation.

This script is long, sorry:

#!/usr/bin/perl

use strict;
use warnings;

#### Files #################
my $in_file = 'calc_hours_in.tex';
open IN, "< $in_file" or die "Could not open your in_file: $!";
my $out_file = 'calc_hours.tex';
open OUT, "> $out_file" or die "Connot create your out_file: $!";
####END Files ##############

my $latex_head = <<"EOF";
\\documentclass[a4]{scrartcl}
\\usepackage[utf8]{inputenc}
[...]

LaTeX loves those backslashes :) . To avoid double-backslash
madness, you could have used different quoting method:

my $latex_head = q{
\documentclass[a4]{scrartcl}
\usepackage[utf8]{inputenc}
....
};

Or you could have read the data in from a separate file.
Good luck.
 
M

Marek Stepanek

I wanted to mention two things in addition to Paul Lalli's comments.

First, you have "STATEMENT if $sum" many times. Just use one if:

if ($sum)
{
a;
b;
c;
}

Yes you are right; this was to avoid the many " uninitialized values " in my
shell!
Thank you, spaciba bolshoi, Ted! My Math-Teacher long long time ago, always
said: "elegance = (practice + studiousness) ^ intelligence ... You must be
very intelligent :)
$random_km = 1.5 + rand(0.3); # random between 1.5 and 1.7999...

That's exactly I wanted to achieve!
Check out "perldoc -f rand" for more info.

Ted


greetings from Munich


marek
 
A

anno4000

[...]
You assigned $km_tag to a string: "185.88 / 1.8". I assume you meant
to assign it to a numerical computation ...

You are using "assign" just opposite to the way I know it. I would
assign a value to a variable, so I would say

You assigned a string: "185.88 / 1.8" to $km_tag. I assume you meant
to assign a numerical computation to it ....

Anno
 
T

Ted Zlatanov

Yes you are right; this was to avoid the many " uninitialized values
" in my shell! Thank you, spaciba bolshoi, Ted!

No problem. I hope you have fun learning Perl - I've been using it
for 10 years and I'm still learning...
That's exactly I wanted to achieve!

I'm glad, I wasn't sure if I understood the original code well.

Ted
 
M

Marek Stepanek

On 16.08.2006 16:39, in article
(e-mail address removed), "Ted Zlatanov"

Thanks to all who responded, Ted, Mumia, Anno, Paul. I am grateful for your
welcome in this group :)

There are many questions coming soon. I hope in a far future, I will be able
to give back the knowledge, which I learned from you.


greetings from Munich


marek
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top