Dot product: Difference between revisions
(→{{header|MATLAB}}: Don't sign your examples, MATLAB highlighting is actually broken) |
|||
Line 230: | Line 230: | ||
<lang> |
<lang> |
||
function c=DotPro(a,b) |
function c=DotPro(a,b) |
||
c=a.*b; |
|||
c=zeros(1,length(a)); |
|||
for i=1:length(a) |
|||
c(i)=a(i)*b(i); |
|||
end |
end |
||
c=sum(c); |
|||
</lang> |
</lang> |
||
Revision as of 16:57, 9 April 2010
You are encouraged to solve this task according to the task description, using any language you may know.
Create a function/use an in-built function, to compute the dot product, also known as the scalar product of two vectors. If possible, make the vectors of arbitrary length.
As an example, compute the dot product of the vectors [1, 3, -5]
and [4, -2, -1]
.
If implementing the dot product of two vectors directly, each vector must be the same length; multiply corresponding terms from each vector then sum the results to produce the answer.
ActionScript
<lang ActionScript>function dotProduct(v1:Vector.<Number>, v2:Vector.<Number>):Number { if(v1.length != v2.length) return NaN; var sum:Number = 0; for(var i:uint = 0; i < v1.length; i++) sum += v1[i]*v2[i]; return sum; } trace(dotProduct(Vector.<Number>([1,3,-5]),Vector.<Number>([4,-2,-1])));</lang>
ALGOL 68
<lang algol68>MODE DOTFIELD = REAL; MODE DOTVEC = [1:0]DOTFIELD;
- The "Spread Sheet" way of doing a dot product:
o Assume bounds are equal, and start at 1 o Ignore round off error
PRIO SSDOT = 7; OP SSDOT = (DOTVEC a,b)DOTFIELD: (
DOTFIELD sum := 0; FOR i TO UPB a DO sum +:= a[i]*b[i] OD; sum
);
- An improved dot-product version:
o Handles sparse vectors o Improves summation by gathering round off error with no additional multiplication - or LONG - operations.
OP * = (DOTVEC a,b)DOTFIELD: (
DOTFIELD sum := 0, round off error:= 0; FOR i
- Assume bounds may not be equal, empty members are zero (sparse) #
FROM LWB (LWB a > LWB b | a | b ) TO UPB (UPB a < UPB b | a | b ) DO DOTFIELD org = sum, prod = a[i]*b[i]; sum +:= prod; round off error +:= sum - org - prod OD; sum - round off error
);
- Test: #
DOTVEC a=(1,3,-5), b=(4,-2,-1);
print(("a SSDOT b = ",fixed(a SSDOT b,0,real width), new line)); print(("a * b = ",fixed(a * b,0,real width), new line))</lang> Output:
a SSDOT b = 3.000000000000000 a * b = 3.000000000000000
C
<lang c>#include <stdio.h>
- include <stdlib.h>
int dot_product(int *, int *, size_t);
int main(void) {
int a[3] = {1, 3, -5}; int b[3] = {4, -2, -1};
printf("%d\n", dot_product(a, b, sizeof(a) / sizeof(a[0])));
return EXIT_SUCCESS;
}
int dot_product(int *a, int *b, size_t n) {
int sum = 0; size_t i;
for (i = 0; i < n; i++) { sum += a[i] * b[i]; }
return sum;
}</lang> Output: <lang>3</lang>
C++
<lang cpp>#include <iostream>
- include <numeric>
int main() {
int a[] = { 1, 3, -5 }; int b[] = { 4, -2, -1 };
std::cout << std::inner_product(a, a + sizeof(a) / sizeof(a[0]), b, 0) << std::endl;
return 0;
}</lang> Output: <lang>3</lang>
Clojure
Preconditions are new in 1.1. The actual code also works in older Clojure versions.
<lang clojure>(defn dot-product [c1 c2]
{:pre [(== (count c1) (count c2))]} (reduce + (map * c1 c2)) )
(println (dot-product [1 3 -5] [4 -2 -1]))</lang>
Factor
The built-in word v.
is used to compute the dot product. It doesn't enforce that the vectors are of the same length, so here's a wrapper.
<lang factor>USING: kernel math.vectors sequences ;
- dot-product ( u v -- w )
2dup [ length ] bi@ = [ v. ] [ "Vector lengths must be equal" throw ] if ;</lang>
( scratchpad ) { 1 3 -5 } { 4 -2 -1 } dot-product . 3
Forth
<lang forth>: vector create cells allot ;
- th cells + ;
3 constant /vector /vector vector a /vector vector b
- dotproduct ( a1 a2 -- n)
0 tuck ?do -rot over i th @ over i th @ * >r rot r> + loop nip nip
- vector! cells over + swap ?do i ! 1 cells +loop ;
-5 3 1 a /vector vector! -1 -2 4 b /vector vector!
a b /vector dotproduct . 3 ok</lang>
Fortran
<lang fortran>program test_dot_product
write (*, '(i0)') dot_product ((/1, 3, -5/), (/4, -2, -1/))
end program test_dot_product</lang> Output: <lang>3</lang>
Haskell
<lang haskell>dotp a b | length a == length b = sum (zipWith (*) a b)
| otherwise = error "Vector sizes must match"
main = print $ dotp [1, 3, -5] [4, -2, -1] -- prints 3</lang>
J
<lang j> 1 3 _5 +/ . * 4 _2 _1 3
dotp=: +/ . * NB. Or defined as a verb (function) 1 3 _5 dotp 4 _2 _1
3</lang>
The conjunction .
applies generally to matricies and arrays of higher dimensions and can be used with verbs (functions) other than sum ( +/
) and product ( *
).
Java
<lang java> public class DotProduct {
public static void main(String[] args) { double[] a = {1, 3, -5}; double[] b = {4, -2, -1};
System.out.println(dotProd(a,b)); }
public static double dotProd(double[] a, double[] b){ if(a.length != b.length){ throw new IllegalArgumentException("The dimensions have to be equal!"); } double sum = 0; for(int i = 0; i < a.length; i++){ sum += a[i] * b[i]; } return sum; } }
</lang>
Output: <lang>3.0</lang>
Logo
<lang logo>to dotprod :a :b
output apply "sum (map "product :a :b)
end
show dotprod [1 3 -5] [4 -2 -1] ; 3</lang>
Lua
<lang lua>function dotprod(a, b)
local ret = 0 for i = 1, #a do ret = ret + a[i] * b[i] end return ret
end
print(dotprod({1, 3, -5}, {4, -2, 1}))</lang>
MATLAB
<lang> function c=DotPro(a,b) c=a.*b; end </lang>
OCaml
<lang ocaml>let dot a b =
let n = Array.length a in if n <> Array.length b then failwith "arrays are not the same length"; let rec g s = function | 0 -> s | i -> g (s +. a.(i-1)*.b.(i-1)) (i-1) in g 0.0 n
dot [| 1.0; 3.0; -5.0 |] [| 4.0; -2.0; -1.0 |];; (* - : float = 3. *)</lang>
Oz
Vectors are represented as lists in this example. <lang oz>declare
fun {DotProduct Xs Ys} {Length Xs} = {Length Ys} %% assert {List.foldL {List.zip Xs Ys Number.'*'} Number.'+' 0} end
in
{Show {DotProduct [1 3 ~5] [4 ~2 ~1]}}</lang>
Perl
<lang perl>sub dotprod (\@\@) {
my($vec_a, $vec_b) = @_; die "they must have the same size\n" unless @$vec_a == @$vec_b; my $sum = 0; $sum += $vec_a->[$_]*$vec_b->[$_] for 0..$#$vec_a; return $sum;
}
my @vec_a = (1,3,-5); my @vec_b = (4,-2,-1);
print dotprod(@vec_a,@vec_b), "\n"; # 3</lang>
Perl 6
Computing the dot product with Perl6 meta operators:
<lang perl6>sub dotProduct( @a, @b ) returns Int { [+] ( @a <<*>> @b ) }
print dotProduct( (1,3,-5), (4,-2,-1) );</lang>
PL/I
<lang PL/I> get (n); begin;
declare (A(n), B(n)) float; declare dot_product float;
get list (A); get list (B); dot_product = sum(a*b); put (dot_product);
end; </lang>
PureBasic
<lang PureBasic>Procedure dotProduct(Array a.i(1), Array b.i(1), length.i)
Protected result.i, i.i For i = 0 To length - 1 result + a(i) * b(i) Next ProcedureReturn result
EndProcedure
Dim a.i(2) a(0) = 1 : a(1) = 3 : a(2) = -5 Dim b.i(2) b(0) = 4 : b(1) = -2 : b(2) = -1
Debug dotProduct(a(), b(), 3) </lang>
Python
<lang python>def dotp(a,b):
assert len(a) == len(b), 'Vector sizes must match' return sum(aterm * bterm for aterm,bterm in zip(a, b))
if __name__ == '__main__':
a, b = [1, 3, -5], [4, -2, -1] assert dotp(a,b) == 3</lang>
R
Here are several ways to do the task.
<lang R> x <- c(1, 3, -5) y <- c(4, -2, -1)
sum(x*y) # compute products, then do the sum x %*% y # inner product
- loop implementation
dotp <- function(x, y) { n <- length(x) if(length(y) != n) stop("invalid argument") s <- 0 for(i in 1:n) s <- s + x[i]*y[i] s }
dotp(x, y) </lang>
Ruby
<lang ruby>class Array
def dot_product(other) raise "not the same size!" if self.length != other.length self.zip(other).inject(0) {|dp, (a, b)| dp += a*b} end
end
p [1, 3, -5].dot_product [4, -2, -1] # => 3</lang>
Scheme
<lang scheme>(define (dot-product a b)
(apply + (map * a b)))
(display (dot-product (list 1 3 -5) (list 4 -2 -1))) (newline)</lang> Output: <lang>3</lang>
Smalltalk
<lang smalltalk>Array extend [
* anotherArray [ |acc| acc := 0. self with: anotherArray collect: [ :a :b | acc := acc + ( a * b ) ]. ^acc ]
]
( #(1 3 -5) * #(4 -2 -1 ) ) printNl.</lang>
SNOBOL4
<lang snobol4> define("dotp(a,b)sum,i") :(dotp_end) dotp i = 1; sum = 0 loop sum = sum + (a * b)
i = i + 1 ?a :s(loop) dotp = sum :(return)
dotp_end
a = array(3); a<1> = 1; a<2> = 3; a<3> = -5; b = array(3); b<1> = 4; b<2> = -2; b<3> = -1; output = dotp(a,b)
end</lang>
Tcl
<lang tcl>package require math::linearalgebra
set a {1 3 -5} set b {4 -2 -1} set dotp [::math::linearalgebra::dotproduct $a $b] proc pp vec {return \[[join $vec ,]\]} puts "[pp $a] \u2219 [pp $b] = $dotp"</lang> Output:
[1,3,-5] ∙ [4,-2,-1] = 3.0
TI-89 BASIC
dotP([1, 3, –5], [4, –2, –1]) 3
Ursala
A standard library function for dot products of floating point numbers exists, but a new one can be defined for integers as shown using the map operator (*
) with the zip suffix (p
) to construct a "zipwith" operator (*p
), which operates on the integer product
function. A catchable exception is thrown if the list lengths are unequal. This function is then composed (+
) with a cumulative summation function, which is constructed from the binary sum
function, and the reduction operator (:-
) with 0
specified for the vacuous sum.
<lang Ursala>#import int
dot = sum:-0+ product*p
- cast %z
test = dot(<1,3,-5>,<4,-2,-1>)</lang> output:
3