Vectors and their arithmetic
Vectors and their arithmetic (lesson 3.1.1)
0 of 7 correct
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
How to type answers
- Powers with
^:x^7,2^(1/3),a^-2. - Multiply with
*or by writing side by side:3x^2,2(x+1). ln(x)is the natural log,log(x, 2)is log base 2,eis Euler's number,sqrt(x)is a square root.sin(x),cos(x)andtan(x)take radians; writepifor π andsin(x)^2for sin²x.- Your first answer to each question is saved: it counts towards your score and brings the question back for review.
- Exact answers like
ln(20)/ln(3)are best. Decimals need about 4 significant figures.
The dot product, length and angle
The dot product, length and angle (lesson 3.1.2)
0 of 7 correct
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
How to type answers
- Powers with
^:x^7,2^(1/3),a^-2. - Multiply with
*or by writing side by side:3x^2,2(x+1). ln(x)is the natural log,log(x, 2)is log base 2,eis Euler's number,sqrt(x)is a square root.sin(x),cos(x)andtan(x)take radians; writepifor π andsin(x)^2for sin²x.- Your first answer to each question is saved: it counts towards your score and brings the question back for review.
- Exact answers like
ln(20)/ln(3)are best. Decimals need about 4 significant figures.
Coding exercise
Unit vectors, angles and shadows
Write three functions, using lesson 3.1.2. Each takes NumPy arrays or plain lists; turn them into float arrays first with np.asarray(x, dtype=float).
unit(u)returns . RaiseValueErrorfor the zero vector.angle_deg(u, v)returns the angle between and in degrees. RaiseValueErrorif the sizes differ or either vector is zero.shadow(v, u)returns the signed length of the shadow of on the line through , . RaiseValueErrorif the sizes differ or is zero.
The tests include parallel and opposite vectors whose computed cosine comes out just past 1 or , so clip it into before np.arccos. They also pass lists, for which + and * would join and repeat rather than add and scale.
See the tests
import math
import numpy as np
def _raises_value_error(f, *args):
try:
f(*args)
except ValueError:
return True
return False
def test_unit():
"""The unit vector of (3, 4) is (0.6, 0.8)"""
expect_close(unit(np.array([3, 4])), np.array([0.6, 0.8]), what="unit((3, 4))")
def test_unit_length_one():
"""The unit vector of (2, −3, 6) has length 1 and points the same way"""
e = unit(np.array([2, -3, 6]))
expect_close(np.linalg.norm(e), 1.0, what="length of unit((2, −3, 6))")
expect_close(e, np.array([2, -3, 6]) / 7, what="unit((2, −3, 6))")
def test_unit_zero():
"""The zero vector has no unit vector: ValueError"""
assert _raises_value_error(unit, np.array([0.0, 0.0])), "expected ValueError for unit((0, 0))"
def test_angles():
"""(3, 1) makes 45° with (1, 2), 90° with (−1, 3) and 135° with (−2, 1)"""
u = np.array([3, 1])
expect_close(angle_deg(u, np.array([1, 2])), 45.0, what="angle between (3, 1) and (1, 2)")
expect_close(angle_deg(u, np.array([-1, 3])), 90.0, what="angle between (3, 1) and (−1, 3)")
expect_close(angle_deg(u, np.array([-2, 1])), 135.0, what="angle between (3, 1) and (−2, 1)")
def test_angle_r3():
"""In three dimensions, (1, 1, 0) and (0, 1, 1) make 60°"""
expect_close(angle_deg(np.array([1, 1, 0]), np.array([0, 1, 1])), 60.0, what="angle between (1, 1, 0) and (0, 1, 1)")
def test_angle_lists():
"""Plain lists work too: [3, 1] and [1, 2] make 45°"""
expect_close(angle_deg([3, 1], [1, 2]), 45.0, what="angle_deg([3, 1], [1, 2])")
def test_parallel():
"""Parallel vectors give 0° and opposite ones 180°, even when rounding pushes the cosine past ±1"""
for given, c in [([3, 1], 0.1), ([3, 1], 1.3), ([1, 2, 3], 1.1), ([2, 3, 6], 0.3), ([1, 1, 1], 1.3)]:
u = np.array(given, dtype=float)
same = angle_deg(u, c * u)
assert not math.isnan(same), f"the angle between {given} and {c} times it came out as nan: clip the cosine into [−1, 1]"
expect_close(same, 0.0, what=f"angle between {given} and {c} times it", abs_tol=1e-6)
opposite = angle_deg(u, -c * u)
assert not math.isnan(opposite), f"the angle between {given} and −{c} times it came out as nan: clip the cosine into [−1, 1]"
expect_close(opposite, 180.0, what=f"angle between {given} and −{c} times it", abs_tol=1e-6)
def test_angle_zero_vector():
"""A zero vector has no angle: ValueError"""
assert _raises_value_error(angle_deg, np.array([0, 0]), np.array([1, 2])), "expected ValueError when u is (0, 0)"
assert _raises_value_error(angle_deg, np.array([3, 1]), np.array([0, 0])), "expected ValueError when v is (0, 0)"
def test_angle_sizes():
"""Vectors of different sizes have no angle: ValueError"""
assert _raises_value_error(angle_deg, np.array([1, 2]), np.array([1, 2, 3])), "expected ValueError for (1, 2) and (1, 2, 3)"
def test_shadow():
"""The shadow of (1, 2) on (3, 1) has length 5/√10, and of (−2, 1) it is −5/√10"""
expect_close(shadow(np.array([1, 2]), np.array([3, 1])), 5 / math.sqrt(10), what="shadow of (1, 2) on (3, 1)")
expect_close(shadow(np.array([-2, 1]), np.array([3, 1])), -5 / math.sqrt(10), what="shadow of (−2, 1) on (3, 1)")
def test_shadow_divides_by_u():
"""The shadow of (1, 7) on (3, 4) is 6.2: divide by the length of (3, 4)"""
expect_close(shadow(np.array([1, 7]), np.array([3, 4])), 6.2, what="shadow of (1, 7) on (3, 4)")
def test_shadow_bad_inputs():
"""No line through the zero vector, and no shadow across sizes: ValueError"""
assert _raises_value_error(shadow, np.array([1, 2]), np.array([0, 0])), "expected ValueError when u is (0, 0)"
assert _raises_value_error(shadow, np.array([1, 2, 3]), np.array([3, 1])), "expected ValueError for sizes 3 and 2"