📄 ch29.htm
字号:
function is derived using the <TT><FONT FACE="Courier">ref()</FONT></TT>
function call in line 46. If the passed parameter is a reference,
then the function uses the first argument; otherwise, <TT><FONT FACE="Courier">$a</FONT></TT>
is assigned to the entire incoming argument list:
<BLOCKQUOTE>
<TT><FONT FACE="Courier">my $a = ref($_[0]) ? $_[0] : \@_;</FONT></TT>
</BLOCKQUOTE>
<P>
The math operations are performed in lines 72 to 79. The results
of these calculations are returned in line 83. Listing 29.1 and
Listing 29.2 should be enough to get you started on creating more
complicated functions. For example, let's add two routines for
performing vector calculations.
<H3><A NAME="DotandCrossProductsofVectors"><B>Dot and Cross Products
of Vectors</B></A></H3>
<P>
Two subroutines that perform the cross and dot products of two
vectors are shown in Listing 29.3. A cross product of a vector
of length <TT><FONT FACE="Courier">n</FONT></TT> and a vector
of length <TT><FONT FACE="Courier">m</FONT></TT> will return a
matrix of size <TT><FONT FACE="Courier">m</FONT></TT> <FONT FACE="Symbol">¥</FONT>
<TT><FONT FACE="Courier">n</FONT></TT>, whereas a dot product
of two vectors of the same size (i.e., <TT><FONT FACE="Courier">m</FONT></TT>
= <TT><FONT FACE="Courier">n</FONT></TT>) will return a scalar
value.
<HR>
<BLOCKQUOTE>
<B>Listing 29.3. Vector functions.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2<BR>
3 #<BR>
4 # Simple statistical functions in Perl<BR>
5 #<BR>
6<BR>
7<BR>
8 #----------------------------------------------------------------
<BR>
9 # Declare
any subroutines here<BR>
10 #----------------------------------------------------------------
<BR>
11 sub xProduct(\@\@\@); # Declare as taking
two pointers to arrays<BR>
12 sub dProduct(\@\@); # Declare
as taking two pointers to arrays<BR>
13<BR>
14 @one = ( 2, 4, 3);<BR>
15 @two = ( 4, -1, 7);<BR>
16 @result = ();<BR>
17<BR>
18 $r = &dProduct(\@one,\@two);<BR>
19<BR>
20 print "\n Dot Product = $r \n";<BR>
21<BR>
22 &xProduct(\@one,\@two,\@result);<BR>
23<BR>
24 print "\n Cross Product = \n";<BR>
25 for ($i=0;$i<3;$i++)
{<BR>
26 for
($j=0;$j< 3;$j++) {<BR>
27 printf "
%4d", $result[$i][$j];<BR>
28 }
<BR>
29 print "\n";<BR>
30 }<BR>
31<BR>
32 exit (0);<BR>
33 # ------------------------------------------------<BR>
34 # Returns dot product of two vectors.<BR>
35 # Takes two pointers to arrays as input<BR>
36 # Returns a scalar.<BR>
37 sub dProduct { #<BR>
38 my ($x,$y) = @_;<BR>
39 my $sum;<BR>
40 my $ct1 = $#{$x} + 1;
# items in $x<BR>
41 my $ct2 = $#{$y} + 1;
# items in $y<BR>
42 return undef if ($ct1 !=
$ct2) ;<BR>
43<BR>
44 for ($i=0;$i<$ct1;$i++)
{<BR>
45 $sum += $$x[$i] * $$y[$i];
<BR>
46 }<BR>
47 return $sum;<BR>
48 }<BR>
49 # ------------------------------------------------<BR>
50 # Returns a cross product of two vectors.<BR>
51 # Takes two pointers to arrays as input<BR>
52 # Returns a two-dimensional array.<BR>
53 sub xProduct {<BR>
54 my ($x,$y) = @_;<BR>
55 my $i, $j, @array;<BR>
56 my $ct1 = $#{$x} + 1; #
items in $x<BR>
57 my $ct2 = $#{$y} + 1; #
items in $y<BR>
58 my $result = \@arrau;<BR>
59 for ($i=0;$i<$ct1;$i++)
{<BR>
60 for
($j=0;$j<$ct2;$j++) {<BR>
61 $$result[$i][$j]
= $$x[$i] * $$y[$i];<BR>
62 #
print " $i, $j, $$result[$i][$j] \n";<BR>
63 }
<BR>
64 }<BR>
64 return ($result); return result.
<BR>
65 }</FONT></TT>
</BLOCKQUOTE>
<HR>
<P>
Notice how the subroutines for the two functions are declared
at lines 11 and 12. At line 18, the script calls <TT><FONT FACE="Courier">dProduct</FONT></TT>
to return the dot product of the two vectors. The return value
from the <TT><FONT FACE="Courier">dProduct</FONT></TT> function
can also be <TT><FONT FACE="Courier">undef</FONT></TT> if the
vectors are not the same size.
<P>
At line 22, you get the resulting cross product matrix of multiplying
the two vectors together. The size of the matrix is M<FONT FACE="Symbol">¥</FONT>N,
where M is the size of the first vector and N is the size of the
second vector passed into <TT><FONT FACE="Courier">xProduct()</FONT></TT>.
<P>
To return an entire result of a calculation instead of having
to pass the <TT><FONT FACE="Courier">@result</FONT></TT> array,
you can rewrite the cross product function as shown in Listing
29.4. Line 9 now declares only two pointers to arrays into <TT><FONT FACE="Courier">xProduct</FONT></TT>.
The array in <TT><FONT FACE="Courier">xProduct</FONT></TT> is
referred to by reference as well at line 53. The reference, <TT><FONT FACE="Courier">$result</FONT></TT>,
is returned to the caller in line 64. Note the <TT><FONT FACE="Courier">@array</FONT></TT>,
even though declared as a <TT><FONT FACE="Courier">my</FONT></TT>
variable, is not destroyed because the reference to it in <TT><FONT FACE="Courier">$result</FONT></TT>
is returned by the <TT><FONT FACE="Courier">xProduct</FONT></TT>
function. As long as the returned reference to the calling program
continues to be used, the space allocated for the <TT><FONT FACE="Courier">@array</FONT></TT>
will not be destroyed.
<H3><A NAME="AddingorSubtractingVectors"><B>Adding or Subtracting
Vectors</B></A></H3>
<P>
It's quite straightforward to include the two functions to add
and subtract two vectors. These two subroutines are defined in
Listing 29.4 at lines 65 and 87, respectively.
<P>
The number of elements in each array passed into the functions
is kept in variables <TT><FONT FACE="Courier">$ct1</FONT></TT>
and <TT><FONT FACE="Courier">$ct2</FONT></TT> (see lines 105 and
106). The counts are used in loops elsewhere in the code.
<HR>
<BLOCKQUOTE>
<B>Listing 29.4. Calculations returning an array.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT><FONT FACE="Courier"> 1 #!/usr/bin/perl<BR>
2<BR>
3 #---------------------------------------------------------------
<BR>
4 # Vector
Arithmetic Routines for use in Perl.<BR>
5 # Copy these freely with NO RESTRICTIONS
AND NO WARRANTY!<BR>
6 #----------------------------------------------------------------
<BR>
7 # Declare
thy subroutines here<BR>
8 #----------------------------------------------------------------
<BR>
9 sub xProduct(\@\@); # Declare as taking
two pointers to arrays<BR>
10 sub dProduct(\@\@); # Declare as taking two
pointers to arrays<BR>
11 sub vAdd(\@\@); #
Declare as taking two pointers to arrays<BR>
12 sub vSubtract(\@\@); # Declare as taking two pointers
to arrays<BR>
13<BR>
14 # -------------------------------------------------------------------
<BR>
15 # Test
with these vectors<BR>
16 # -------------------------------------------------------------------
<BR>
17 @one = ( 2, 4, 3);<BR>
18 @two = ( 4, -1, 7);<BR>
19 @result = ();<BR>
20<BR>
21 print "\n Vector 1 = ";<BR>
22 for (@one) { printf " %4d", $_; }<BR>
23<BR>
24 print "\n Vector 2 = ";<BR>
25 for (@two) { printf " %4d", $_; }<BR>
26<BR>
27<BR>
28 # -------------------------------------------------------------------
<BR>
29 # Test
Dot Product<BR>
30 # -------------------------------------------------------------------
<BR>
31 $r = &dProduct(@one,@two);<BR>
32 print "\n Dot Product = $r \n";<BR>
33<BR>
34 # -------------------------------------------------------------------
<BR>
35 # Test
Addition<BR>
36 # -------------------------------------------------------------------
<BR>
37 @result = &vAdd(\@one,\@two);<BR>
38 print "\n Added = ";<BR>
39 for (@result) { printf
" %4d", $_; }<BR>
40<BR>
41 # -------------------------------------------------------------------
<BR>
42 # Test
Subtraction<BR>
43 # -------------------------------------------------------------------
<BR>
44 @result = &vSubtract(\@one,\@two);<BR>
45 print "\n Subtract = ";<BR>
46 for (@result) { printf
" %4d", $_; }<BR>
47<BR>
48 # -------------------------------------------------------------------
<BR>
49 # Test
Cross Product<BR>
50 # -------------------------------------------------------------------
<BR>
51 @result = &xProduct(\@one,\@two);<BR>
52<BR>
53 print "\n Cross Product = \n";<BR>
54 for ($i=0;$i<3;$i++)
{<BR>
55 for
($j=0;$j< 3;$j++) {<BR>
56 printf "
%4d", $result[$i][$j];<BR>
57
}<BR>
58 print "\n";
<BR>
59 }<BR>
60<BR>
61 exit (0);<BR>
62<BR>
63 # -------------------------------------------------------------------
<BR>
64 # Returns a vector that is the result of subtracting
one vector from<BR>
65 # another. Both vectors have to be the same size.<BR>
66 # -------------------------------------------------------------------
<BR>
67 sub vAdd { # (\@\@); Declare as taking two
pointers to arrays<BR>
68 my ($x,$y) = @_;<BR>
69 my $ct1 = $#{$x} +
1; # items in $x<BR>
70 my $ct2 = $#{$y} +
1; # items in $y<BR>
71 return undef if ($ct1
!= $ct2) ;<BR>
72 my $i;<BR>
73 my @answer;<BR>
74<BR>
75 for ($i=0;$i<$ct1;$i++)
{<BR>
76 $answer[$i]
= $$x[$i] + $$y[$i];<BR>
77 }<BR>
78 return @answer;<BR>
79 }<BR>
80<BR>
81 # -------------------------------------------------------------------
<BR>
82 # Returns a vector that is the result of subtracting
one vector from<BR>
83 # another. Both vectors have to be the same size.<BR>
84 # -------------------------------------------------------------------
<BR>
85 sub vSubtract { # (\@\@); Declare as taking
two pointers to arrays<BR>
86 my ($x,$y) = @_;<BR>
87 my $ct1 = $#{$x} +
1; # items in $x<BR>
88 my $ct2 = $#{$y} +
1; # items in $y<BR>
89 return undef if ($ct1
!= $ct2) ;<BR>
90 my $i;<BR>
91 my @answer;<BR>
92<BR>
93 for ($i=0;$i<$ct1;$i++)
{<BR>
94 $answer[$i]
= $$x[$i] - $$y[$i];<BR>
95 }<BR>
96 return @answer;<BR>
97 }<BR>
98<BR>
99 # -------------------------------------------------------------------
<BR>
100 # Returns a scalar that is a dot product of two vectors.<BR>
101 # -------------------------------------------------------------------
<BR>
102 sub dProduct { # (\@\@); Declare as taking two
pointers to arrays<BR>
103 my ($x,$y) = @_;<BR>
104 my $sum;<BR>
105 my $ct1 = $#{$x} + 1; #
items in $x<BR>
106 my $ct2 = $#{$y} + 1; #
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -