├── .gitignore
├── .npmignore
├── CONTRIBUTING.md
├── LICENSE.md
├── PYTHON-README.md
├── README-zh.md
├── README.md
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 | *.log
4 | .DS_Store
5 | bundle.js
6 | test.js
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 | *.log
4 | .DS_Store
5 | bundle.js
6 | test
7 | test.js
8 | demo/
9 | .npmignore
10 | LICENSE.md
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | ### Issues
4 |
5 | If you see errors in the math, problems in the wording/language, or issues with how a symbol/equation translates into code, please create an issue.
6 |
7 | Please [search existing issues](https://github.com/Jam3/math-as-code/issues) before posting a new one.
8 |
9 | ### Pull Requests
10 |
11 | Pull requests are awesome! :tada: If you are going to be adding a new feature or making major changes, it's best to open a new issue to discuss it before you go ahead and work on the PR.
12 |
13 | Some other guidelines:
14 |
15 | - Keep PRs clean, and only change parts that are relevant to your feature/fix. Different features/fixes are best submitted as independent PRs.
16 | - Some unicode symbols can be used inline, but overall the goal of this is to demystify the equations commonly found in literature. Please use LaTeX SVGs, see the next point.
17 | - Currently, equations are authored with [this LaTeX editor](http://www.codecogs.com/latex/eqneditor.php), with SVG selected, and images are linked directly to the resulting URL.
18 | - Also include the raw LaTeX as a Markdown comment directly below the image. Comments use the form: ``
19 | - Code should be syntax highlighted with `js` and follow [this style guide](https://github.com/feross/standard).
20 | - Please try to maintain the overall writing style in any new changes.
21 |
22 |
23 | #### LaTeX Example
24 |
25 | Here is an example of how a new equation might look in LaTeX:
26 |
27 | ```md
28 | 
29 |
30 |
37 | ```
38 |
39 | The rendered result:
40 |
41 | 
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2015 Jam3
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
20 | OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 |
--------------------------------------------------------------------------------
/PYTHON-README.md:
--------------------------------------------------------------------------------
1 | # math-as-code (Python version)
2 |
3 | >[Chinese translation of javascript version (中文版)](./README-zh.md)
4 | >[JavaScript version (English)](./README.md)
5 |
6 | This is a reference to ease developers into mathematical notation by showing comparisons with Python code.
7 |
8 | Motivation: Academic papers can be intimidating for self-taught graphics programmers and data wranglers :)
9 |
10 | This guide is not yet finished. If you see errors or want to contribute, please [open a ticket](https://github.com/Jam3/math-as-code/issues) or send a PR.
11 |
12 | > **Note**: There will be some discussion of vectorization with [numpy](https://www.numpy.org/).
13 |
14 | > **Note**: We're only looking at `python3`, if there are significant differences with `python2` please bring them up in issues.
15 |
16 |
17 | # foreword
18 |
19 | Mathematical symbols can mean different things depending on the author, context and the field of study (linear algebra, set theory, etc). This guide may not cover *all* uses of a symbol. In some cases, real-world references (blog posts, publications, etc) will be cited to demonstrate how a symbol might appear in the wild.
20 |
21 | For a more complete list, refer to [Wikipedia - List of Mathematical Symbols](https://en.wikipedia.org/wiki/List_of_mathematical_symbols).
22 |
23 | For simplicity, many of the code examples here operate on floating point values and are not numerically robust. For more details on why this may be a problem, see [Robust Arithmetic Notes](https://github.com/mikolalysenko/robust-arithmetic-notes) by Mikola Lysenko.
24 |
25 | # contents
26 |
27 | - [variable name conventions](#variable-name-conventions)
28 | - [equals `=` `≈` `≠` `:=`](#equals-symbols)
29 | - [square root and complex numbers `√` *`i`*](#square-root-and-complex-numbers)
30 | - [dot & cross `·` `×` `∘`](#dot--cross)
31 | - [scalar multiplication](#scalar-multiplication)
32 | - [vector multiplication](#vector-multiplication)
33 | - [dot product](#dot-product)
34 | - [cross product](#cross-product)
35 | - [sigma `Σ`](#sigma) - *summation*
36 | - [capital Pi `Π`](#capital-pi) - *products of sequences*
37 | - [pipes `||`](#pipes)
38 | - [absolute value](#absolute-value)
39 | - [Euclidean norm](#euclidean-norm)
40 | - [determinant](#determinant)
41 | - [hat **`â`**](#hat) - *unit vector*
42 | - ["element of" `∈` `∉`](#element)
43 | - [common number sets `ℝ` `ℤ` `ℚ` `ℕ`](#common-number-sets)
44 | - [function `ƒ`](#function)
45 | - [piecewise function](#piecewise-function)
46 | - [common functions](#common-functions)
47 | - [function notation `↦` `→`](#function-notation)
48 | - [prime `′`](#prime)
49 | - [floor & ceiling `⌊` `⌉`](#floor--ceiling)
50 | - [arrows](#arrows)
51 | - [material implication `⇒` `→`](#material-implication)
52 | - [equality `<` `≥` `≫`](#equality)
53 | - [conjunction & disjunction `∧` `∨`](#conjunction--disjunction)
54 | - [logical negation `¬` `~` `!`](#logical-negation)
55 | - [intervals](#intervals)
56 | - [more...](#more)
57 |
58 | ## variable name conventions
59 |
60 | There are a variety of naming conventions depending on the context and field of study, and they are not always consistent. However, in some of the literature you may find variable names to follow a pattern like so:
61 |
62 | - *s* - italic lowercase letters for scalars (e.g. a number)
63 | - **x** - bold lowercase letters for vectors (e.g. a 2D point)
64 | - **A** - bold uppercase letters for matrices (e.g. a 3D transformation)
65 | - *θ* - italic lowercase Greek letters for constants and special variables (e.g. [polar angle *θ*, *theta*](https://en.wikipedia.org/wiki/Spherical_coordinate_system))
66 |
67 | This will also be the format of this guide.
68 |
69 | ### Numpy
70 | Numpy is a powerful **array programming** library, which in python can be
71 | interpreted as a **domain specific language** (DSL). Sometimes it's helpful to
72 | think of math in python as two languages sharing a namespace, with special
73 | [syntax sugar](https://en.wikipedia.org/wiki/Syntactic_sugar) to access one or
74 | the other. This will be important in our vectors and matrices section, because
75 | *slightly different python syntax means different speeds at large input*. The
76 | convention is `import numpy as np`, so when you see `np.something` you know that
77 | we're working in numpy.
78 |
79 | ## equals symbols
80 |
81 | There are a number of symbols resembling the equals sign `=`. Here are a few common examples:
82 |
83 | - `=` is for equality (values are the same)
84 | - `≠` is for inequality (value are not the same)
85 | - `≈` is for approximately equal to (`π ≈ 3.14159`)
86 | - `:=` is for definition (A is defined as B)
87 |
88 | In Python:
89 |
90 | ```python
91 | ## equality
92 | 2 == 3
93 |
94 | ## inequality
95 | 2 != 3
96 |
97 | ## approximately equal
98 | import math
99 | math.isclose(math.pi, 3.14159) # math.isclose doesn't have a third argument for tolerance, so this is false
100 |
101 | from numpy.testing import assert_almost_equal
102 | assert_almost_equal(math.pi, 3.14159, 1e-5) # we gave it a the tolerance we want, 5 decimal places.
103 | # This is actually a unit test, equivalent to "assert isclose(x,y)", read on for more.
104 |
105 | def almost_equal(x, y, epsilon=7):
106 | ''' you can make your own!
107 | in numpy, 1e-7 is the default epsilon
108 | '''
109 | return abs(x - y) < 10 ** -epsilon
110 |
111 | ```
112 |
113 | > **Read more**: programmers got this idea from the [epsilon-delta definition of limit][1]
114 |
115 | **Note**: subclasses of [`unittest.TestCase`](https://docs.python.org/3/library/unittest.html) come with their own `assertAlmostEqual`.
116 |
117 | **Warning**: *please* don't use exact `==` equality on floats!
118 |
119 | In mathematical notation, you might see the `:=`, `=:` and `=` symbols being used for *definition*.[2]
120 |
121 | For example, the following defines *x* to be another name for 2*kj*.
122 |
123 | 
124 |
125 |
126 |
127 | In python, we *define* our variables and provide aliases with `=`.
128 |
129 | ```python
130 | x = 2 * k * j
131 | ```
132 | *Assignment* in python is generally *mutable* besides special cases like `Tuple`.
133 |
134 | > **Note**: Some languages have pre-processor `#define` statements, which are closer to a mathematical *define*.
135 |
136 | Notice that `def` is a form of `:=` as well.
137 | ```python
138 | def plus(x, y):
139 | return x + y
140 | ```
141 |
142 | The following, on the other hand, represents equality:
143 |
144 | 
145 |
146 |
147 |
148 | **Important**: the difference between `=` and `==` can be more obvious in code than it is in math literature! In python, a `=` is an *instruction*. You're telling the machine to interact with the namespace, add something to it or change something in it. In python, when you write `==` you're asking the machine "may I have a `bool`?". In math, the former case is *either* covered by `:=` or `=`, while the latter case is *usually* `=`, and you might have to do some disambiguating in your reading.
149 |
150 | In math, when I write 1 + 1 = 2 I'm making a *judgment*. It's not that i'm asking the world (or the chalkboard) for a bool, it's that I'm keeping track of my beliefs. This distinction is the foundation of *unit tests* or *assertions*.
151 |
152 | ```python
153 |
154 | # assert in python takes an expression that lands in bool and a string to be printed if it turns out false.
155 | assert plus(1, 1) == 2, "DANGER: PHYSICS IS BROKEN. PLEASE STAY INSIDE. "
156 | ```
157 |
158 | It's important to know *when a falsehood ought to crash a program* vs. when you just want a boolean value. To understand this better, read [this][3].
159 |
160 |
161 |
162 |
163 | ## square root and complex numbers
164 |
165 | A square root operation is of the form:
166 |
167 | 
168 |
169 |
170 |
171 | In programming we use a `sqrt` function, like so:
172 |
173 | ```python
174 | import math
175 | print(math.sqrt(2))
176 | # Out: 1.4142135623730951
177 |
178 | import numpy as np
179 | print(np.sqrt(2))
180 | # Out: 1.4142135623730951
181 |
182 | ```
183 |
184 | Complex numbers are expressions of the form , where  is the real part and  is the imaginary part. The imaginary number  is defined as:
185 |
186 | .
187 |
188 |
189 | Vanilla python has a `complex` constructor, and a standard module `cmath` for working with them.
190 |
191 | ```python
192 | complex(1,1)
193 | # Out: (1+1j)s
194 |
195 | math.sqrt(complex(1,1))
196 | # TypeError: can't convert complex to float
197 |
198 | import cmath
199 | cmath.sqrt(complex(1,1))
200 | # Out: (1.09868411346781+0.45508986056222733j)
201 |
202 | # you need numpy to get conjugate
203 | np.conj(complex(0.5,0.5))
204 | # Out: (0.5-0.5j)
205 |
206 | # we can represent the basic meaning of the imaginary unit like so
207 | assert cmath.sqrt(complex(-1, 0)) == complex(0,1)
208 | ```
209 |
210 | As you can see, it uses `j` to denote the imaginary unit, instead of `i`.
211 |
212 | The **conjugate** of a complex number is **flipping the sign of the imaginary part**.
213 |
214 | If `z` is a python `complex` number, `z.real` gets the real part (exactly as an
215 | object attribute) and `z.imag` gets the imaginary part.
216 |
217 | Just as complex numbers can be interpreted as a sort of wrapper around tuples of
218 | reals, a complex number data type wraps two floats. Numpy uses this to implement
219 | complex numbers of different sizes/precisions.
220 |
221 | The syntax is close enough to `cmath`, but it comes with the power and
222 | convenience of numpy. Importantly, other numpy methods are better at *casting*
223 | to and from complex.
224 |
225 |
226 | observe the following [cube roots of unity](https://www.math-only-math.com/the-cube-roots-of-unity.html)
227 | ```python
228 | z1 = 0.5 * np.complex(-1, math.sqrt(3)) # Numpy's constructor is basically the same.
229 | z2 = np.conj(z1) # but numpy gives us a conjugation function, while the standard module does not.
230 |
231 | assert math.isclose(z1**3, z2**3)
232 | # TypeError: can't convert complex to float
233 |
234 | np.testing.assert_almost_equal(z1**3, z2**3)
235 | ```
236 | [Read on about numpy's complex numbers](https://docs.scipy.org/doc/numpy/user/basics.types.html)
237 |
238 | ## dot & cross
239 |
240 | The dot `·` and cross `×` symbols have different uses depending on context.
241 |
242 | They might seem obvious, but it's important to understand the subtle differences before we continue into other sections.
243 |
244 | #### scalar multiplication
245 |
246 | Both symbols can represent simple multiplication of scalars. The following are equivalent:
247 |
248 | 
249 |
250 |
251 |
252 | In programming languages we tend to use asterisk for multiplication:
253 |
254 | ```python
255 | result = 5 * 4
256 | ```
257 |
258 | Often, the multiplication sign is only used to avoid ambiguity (e.g. between two numbers). Here, we can omit it entirely:
259 |
260 | 
261 |
262 |
263 |
264 | If these variables represent scalars, the code would be:
265 |
266 | ```python
267 | result = 3 * k * j
268 | ```
269 |
270 | #### vector multiplication
271 |
272 | To denote multiplication of one vector with a scalar, or element-wise multiplication of a vector with another vector, we typically do not use the dot `·` or cross `×` symbols. These have different meanings in linear algebra, discussed shortly.
273 |
274 | Let's take our earlier example but apply it to vectors. For element-wise vector multiplication, you might see an open dot `∘` to represent the [Hadamard product](https://en.wikipedia.org/wiki/Hadamard_product_%28matrices%29).[2]
275 |
276 | 
277 |
278 |
279 |
280 | In other instances, the author might explicitly define a different notation, such as a circled dot `⊙` or a filled circle `●`.[3]
281 |
282 | Here is how it would look in code, using arrays `[x, y]` to represent the 2D vectors.
283 |
284 | ```python
285 | s = 3
286 | k = [1, 2]
287 | j = [2, 3]
288 |
289 | tmp = multiply(k, j)
290 | result = multiply_scalar(tmp, s)
291 | # Out: [6, 18]
292 | ```
293 |
294 | Our `multiply` and `multiply_scalar` functions look like this:
295 |
296 | ```python
297 | def multiply(a, b):
298 | return [aa * bb for aa,bb in zip(a,b)
299 |
300 |
301 | def multiply_scalar(scalar, a):
302 | return [scalar * aa for aa in a]
303 |
304 | ```
305 |
306 | Similarly, matrix multiplication typically does not use the dot `·` or cross symbol `×`.
307 |
308 | Numpy's broadcasted syntax for scaling looks like this:
309 |
310 | ```python
311 | def multiply_scalar(scalar, a):
312 | return scalar * np.array(a)
313 | ```
314 |
315 | #### dot product
316 |
317 | The dot symbol `·` can be used to denote the [*dot product*](https://en.wikipedia.org/wiki/Dot_product) of two vectors. Sometimes this is called the *scalar product* since it evaluates to a scalar.
318 |
319 | 
320 |
321 |
322 |
323 | It is a very common feature of linear algebra, and with a 3D vector it might look like this:
324 |
325 | ```python
326 | k = [0, 1, 0]
327 | j = [1, 0, 0]
328 |
329 | d = np.dot(k, j)
330 | # Out: 0
331 | ```
332 |
333 | The result `0` tells us our vectors are perpendicular. Here is a `dot` function for 3-component vectors:
334 |
335 | ```python
336 | def dot(a, b):
337 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
338 | ```
339 |
340 | #### cross product
341 |
342 | The cross symbol `×` can be used to denote the [*cross product*](https://en.wikipedia.org/wiki/Cross_product) of two vectors.
343 |
344 | 
345 |
346 |
347 |
348 | In code, it would look like this:
349 |
350 | ```python
351 | k = [0, 1, 0]
352 | j = [1, 0, 0]
353 |
354 | result = cross(k, j)
355 | # Out: [ 0, 0, -1 ]
356 | ```
357 |
358 | Here, we get `[0, 0, -1]`, which is perpendicular to both **k** and **j**.
359 |
360 | Our `cross` function:
361 |
362 | ```python
363 | def cross(a, b):
364 | ''' take two 3D vectors and return their cross product. '''
365 | rx = a[1] * b[2] - a[2] * b[1]
366 | ry = a[2] * b[0] - a[0] * b[2]
367 | rz = a[0] * b[1] - a[1] * b[0]
368 | return rx, ry, rz
369 | ```
370 |
371 | It's good to practice and grok these operations, but in real life you'll use
372 | Numpy.
373 |
374 | ## sigma
375 |
376 | The big Greek `Σ` (Sigma) is for [Summation](https://en.wikipedia.org/wiki/Summation). In other words: summing up some numbers.
377 |
378 | 
379 |
380 |
381 |
382 | Here, `i=1` says to start at `1` and end at the number above the Sigma, `100`. These are the lower and upper bounds, respectively. The *i* to the right of the "E" tells us what we are summing. In code:
383 |
384 | Hence, the big sigma is the `for` keyword.
385 | ```python
386 | sum([k for k in range(100)])
387 | # Out: 5050
388 | ```
389 |
390 | **Tip:** With whole numbers, this particular pattern can be optimized to the
391 | following (and try to [grok the
392 | proof](http://mathcentral.uregina.ca/QQ/database/QQ.02.06/jo1.html). The legend
393 | of how Gauss discovered I can only describe as "typical programmer antics"):
394 |
395 | ```python
396 | def sum_to_n(n):
397 | ''' return the sum of integers from 0 to n'''
398 | return 0.5 * n * (n + 1)
399 | ```
400 |
401 | Here is another example where the *i*, or the "what to sum," is different:
402 |
403 | 
404 |
405 |
406 |
407 | In code:
408 |
409 | ```python
410 | sum([2*k + 1 for k in range(100)])
411 | # Out: 10000
412 | ```
413 |
414 | **important**: `range` in python has an *inclusive lower bound and exclusive
415 | upper bound*, meaning that `... for k in range(100)` is equivalent to `the sum of
416 | ... for k=0 to k=n`.
417 |
418 | If you're still not absolutely fluent in indexing for these applications, spend some time with [Trev Tutor](https://youtu.be/TDpQSa3hJRw) on youtube.
419 |
420 | The notation can be nested, which is much like nesting a `for` loop. You should
421 | evaluate the right-most sigma first, unless the author has enclosed them in
422 | parentheses to alter the order. However, in the following case, since we are
423 | dealing with finite sums, the order does not matter.
424 |
425 | 
426 |
427 |
428 |
429 | In code:
430 |
431 | ```python
432 | sum(
433 | [sum([3*i*j
434 | for j
435 | in range(4,7)])
436 | for i
437 | in range(1,3)])
438 | # Out: 135
439 | ```
440 |
441 |
442 | ## capital Pi
443 |
444 | The capital Pi or "Big Pi" is very similar to [Sigma](#sigma), except we are using multiplication to find the product of a sequence of values.
445 |
446 | Take the following:
447 |
448 | 
449 |
450 |
451 |
452 | This was removed from vanilla python for python 3, but it's easy to recover with
453 | a generalization of the list accumulator.
454 | ```python
455 | def times(x, y):
456 | ''' first, give a name to the multiplication operator '''
457 | return x * y
458 |
459 | from functools import reduce
460 |
461 | reduce(times, range(1,7))
462 | # Out: 720
463 | ```
464 |
465 | With reduce, you can actually repeatedly apply a binary function to items of a
466 | list and accumulate the value _for any binary operator_. Python gives `and` and
467 | `or` out of the box like `sum`, but keep `reduce` in mind if you encounter a
468 | less common binary operator out in the wild.
469 |
470 | Note that in Numpy arrays, the syntax is different (and product is given out of
471 | the box)
472 |
473 | ```python
474 | import numpy as np
475 |
476 | xs = np.array([2*k + 1 for k in range(100)])
477 | ys = np.array(range(1,7))
478 |
479 | xs.sum()
480 | # Out: 10000
481 |
482 | ys.prod()
483 | # Out: 720
484 | ```
485 | which is better on larger input, but you're always welcome to use functions for
486 | ordinary lists as you please.
487 |
488 | ## pipes
489 |
490 | Pipe symbols, known as *bars*, can mean different things depending on the
491 | context. Below are three common uses: [absolute value](#absolute-value),
492 | [Euclidean norm](#euclidean-norm), and [determinant](#determinant).
493 |
494 | These three features all describe the *length* of an object.
495 |
496 | #### absolute value
497 |
498 | 
499 |
500 |
501 |
502 | For a number *x*, `|x|` means the absolute value of *x*. In code:
503 |
504 | ```python
505 | x = -5
506 | abs(x)
507 | # Out: 5
508 | ```
509 | #### Euclidean norm
510 |
511 | 
512 |
513 |
514 |
515 | For a vector **v**, `‖v‖` is the [Euclidean norm](https://en.wikipedia.org/wiki/Norm_%28mathematics%29#Euclidean_norm) of **v**. It is also referred to as the "magnitude" or "length" of a vector.
516 |
517 | Often this is represented by double-bars to avoid ambiguity with the *absolute value* notation, but sometimes you may see it with single bars:
518 |
519 | 
520 |
521 |
522 |
523 | Here is an example using an array `[x, y, z]` to represent a 3D vector.
524 |
525 | ```python
526 | v = [0, 4, -3]
527 | length(v)
528 | # Out: 5.0
529 |
530 | ```
531 |
532 | The `length** function:
533 |
534 | ```python
535 | def length(vec):
536 | x = vec[0]
537 | y = vec[1]
538 | z = vec[2]
539 | return math.sqrt(x**2 + y**2 + z**2)
540 | ```
541 |
542 | The implementation for arbitrary length'd vectors is left as an exercise for the
543 | reader.
544 |
545 | In practice, you'll probably use the following numpy call
546 |
547 | ```python
548 | np.linalg.norm([0, 4, -3])
549 | # Out: 5.0
550 | ```
551 |
552 | Resources:
553 | - [numpy.linalg docs](get link to numpy.linalg docs)
554 |
555 | #### determinant
556 |
557 | 
558 |
559 |
560 |
561 | For a matrix **A**, `|A|` means the
562 | [determinant](https://en.wikipedia.org/wiki/Determinant) of matrix **A**.
563 |
564 | Here is an example computing the determinant of a 2x2 identity matrix
565 |
566 | ```python
567 | ident_2 = [[1, 0],
568 | [0, 1]]
569 |
570 | np.linalg.det(ident_2)
571 | # Out: 1
572 | ```
573 |
574 | You should watch [3blue1brown](https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab), but in short if a matrix (list of list of numbers)
575 | is interpreted as hitting a **coordinate system** with a
576 | *squisher-stretcher-rotater*, the determinant of that matrix is the **measure of
577 | how much the unit area/volume of the coordinate system got
578 | squished-stretched-rotated**.
579 |
580 | ```python
581 | np.linalg.det(np.identity(100)) # the determinant of the 100 x 100 identity matrix is still one, because the identity matrix doesn't squish, stretch, or rotate at all.
582 | # Out: 1.0
583 |
584 | np.linalg.det(np.array([[0, -1], [1, 0]])) # 90 degree rotation.
585 | # Out: 1.0
586 |
587 | ```
588 |
589 | The second matrix was the [**2D rotation**](https://en.wikipedia.org/wiki/Rotation_matrix) at 90 degrees.
590 |
591 | ## hat
592 |
593 | In geometry, the "hat" symbol above a character is used to represent a [unit vector](https://en.wikipedia.org/wiki/Unit_vector). For example, here is the unit vector of **a**:
594 |
595 | 
596 |
597 |
598 |
599 | In Cartesian space, a unit vector is typically length 1. That means each part of the vector will be in the range of -1.0 to 1.0. Here we *normalize* a 3D vector into a unit vector:
600 |
601 | ```python
602 | a = [ 0, 4, -3 ]
603 | normalize(a)
604 | # Out: [ 0, 0.8, -0.6 ]
605 | ```
606 |
607 | If a vector is that which has magnitude and direction, normalization of a vector
608 | is the operation that deletes magnitude and preserves direction.
609 |
610 | Here is the `normalize` function, operating on 3D vectors:
611 |
612 | ```python
613 | def normalize(vec):
614 | x = vec[0]
615 | y = vec[1]
616 | z = vec[2]
617 | squaredLength = x * x + y * y + z * z
618 |
619 | if (squaredLength > 0):
620 | length = math.sqrt(squaredLength)
621 | vec[0] = x / length
622 | vec[1] = y / length
623 | vec[2] = z / length
624 |
625 | return vec
626 | ```
627 |
628 | Which Numpy's **broadcasting** syntax sugar can do in fewer lines
629 |
630 | You should try to generalize this to vectors of arbitrary length yourself,
631 | before reading this...
632 |
633 | Go, I mean it!
634 |
635 | ```python
636 | def normalize(vec):
637 | ''' *sigh* if you don't do it yourself you'll never learn! '''
638 | vec = np.array(vec) # ensure that input is casted to numpy
639 | length = np.linalg.norm(vec)
640 | if length > 0:
641 | return vec / length
642 | ```
643 | Notice that **broadcasting** here is just short for `[x / length for x in vec]`.
644 | But it's actually **faster** on large input, because arrays.
645 |
646 | [*Read* the Numpy docs. *BE* the Numpy docs](https://docs.scipy.org/doc/numpy/reference/routines.linalg.html)
647 |
648 |
649 | ## element
650 |
651 | In set theory, the "element of" symbol `∈` and `∋` can be used to describe whether something is an element of a *set*. For example:
652 |
653 | 
654 |
655 |
656 |
657 | Here we have a set of numbers *A* = `{ 3, 9, 14 }` and we are saying `3` is an "element of" that set.
658 |
659 | The `in` keyword plays the role of the elementhood function, giving a bool.
660 |
661 | ```python
662 | A = [ 3, 9, 14 ]
663 |
664 | 3 in A
665 | # Out: True
666 | ```
667 |
668 | Python also has `set`. You can wrap any iterable or generator with the `set` keyword to delete
669 | repeats.
670 |
671 | ```python
672 | set([3,3,3,2,4,3,3,3,1,2,4,5,3])
673 | # Out: {1, 2, 3, 4, 5}
674 |
675 | 3 in set(range(1, 20, 4))
676 | # Out: False
677 | ```
678 |
679 | The backwards `∋` is the same, but the order changes:
680 |
681 | 
682 |
683 |
684 |
685 | You can also use the "not an element of" symbols `∉` and `∌` like so:
686 |
687 | 
688 |
689 |
690 |
691 | Which you know is represented by the convenient `not` keyword in python.
692 |
693 | ## common number sets
694 |
695 | You may see some some large [Blackboard](https://en.wikipedia.org/wiki/Blackboard_bold) letters among equations. Often, these are used to describe sets.
696 |
697 | For example, we might describe *k* to be an [element of](#element) the set `ℝ`.
698 |
699 | 
700 |
701 |
702 |
703 | Listed below are a few common sets and their symbols.
704 |
705 | #### `ℝ` real numbers
706 |
707 | The large `ℝ` describes the set of *real numbers*. These include integers, as well as rational and irrational numbers.
708 |
709 | Computers approximate `ℝ` with `float`.
710 |
711 | You can use `isinstance` to check "*k* ∈ ℝ", where float and `ℝ` aren't *really*
712 | the same thing but the intuition is close enough.
713 |
714 | ```python
715 | isinstance(np.pi, float)
716 | # Out: True
717 | ```
718 |
719 | Again, you may elevate that bool to an `assertion` that makes-or-breaks the whole program
720 | with the `assert` keyword when you see fit.
721 |
722 | [Excellent resource on floats in python](https://youtu.be/zguLmgYWhM0)
723 |
724 | #### `ℚ` rational numbers
725 |
726 | Rational numbers are real numbers that can be expressed as a fraction, or
727 | *ratio*. Rational numbers cannot have zero as a denominator.
728 |
729 | Imagine taking `ℝ` and removing radicals (like `np.sqrt`) and logarithms (in a
730 | family called
731 | [transcendentals](https://en.wikipedia.org/wiki/Transcendental_function)),
732 | that's basically what `ℚ` is, at least enough for a rough first approximation.
733 |
734 | This also means that all integers are rational numbers, since the denominator can be expressed as 1.
735 |
736 | An irrational number, on the other hand, is one that cannot be expressed as a ratio, like π (`math.pi`).
737 |
738 | A reason a programmer might care about the difference between Q and R is in the
739 | design of unit tests--- *fractions are terminating decimals*, and sometimes when
740 | you're a 100% sure that a number will be a basic rational (like counting change,
741 | `0.25, 0.10, 0.05`, etc.), you're allowed to use `==` in unit tests rather than
742 | `isclose` or `assert_almost_equal`. The point is that you know not to use exact
743 | equality `==` when anything like `sqrt` or `log` is involved!
744 |
745 | You can work with rationals without dividing them into floatiness with the
746 | [`fractions` standard module](https://docs.python.org/3.7/library/fractions.html)
747 |
748 | #### `ℤ` integers
749 |
750 | An integer is a whole number. Just imagine starting from zero and one and
751 | building out an inventory with addition and subtraction.
752 |
753 | An integer has no division, no decimals.
754 |
755 | ```python
756 | assert isinstance(8/7, int), "GO DIRECTLY TO JAIL"
757 | ```
758 |
759 | #### `ℕ` natural numbers
760 |
761 | A natural number, a non-negative integer.
762 |
763 | This is actually the only set invented by the [flying spaghetti monster](https://www.brainyquote.com/quotes/leopold_kronecker_338745): as for the
764 | others, humans have themselves to blame.
765 |
766 | Depending on the context and field of study, the set may or may not **start with zero**.
767 |
768 | ...ok but, between you and me, **they 200% start with zero**.
769 |
770 | `ℕ` also happens to be the first **inductive construction** in the [study of
771 | datatypes](https://en.wikipedia.org/wiki/Semantics_(computer_science)), consisting of a single axiom ("Zero is a `ℕ`") and a single
772 | inference rule ("if `n` is a `ℕ` then `n + 1` is also a `ℕ`")
773 |
774 | `ℕ` is not a datatype in python, we can't use *typechecking* to disambiguate `int`
775 | from `non-negative int`, but in a pinch you could easily write up something that
776 | combines `x >= 0` judgments with `isinstance(x, int)`.
777 |
778 | #### `ℂ` complex numbers
779 |
780 | As we saw earlier, the complex numbers are a particular wrapper around tuples of
781 | reals.
782 |
783 | A complex number is a combination of a real and imaginary number, viewed as a co-ordinate in the 2D plane. For more info, see [A Visual, Intuitive Guide to Imaginary Numbers](http://betterexplained.com/articles/a-visual-intuitive-guide-to-imaginary-numbers/).
784 |
785 | We can say `ℂ = {a + b*i | a,b ∈ ℝ}`, which is a notation called
786 |
787 | ## Set builder notation
788 |
789 | Pythoners have a name for *set builder notation*; and the name is comprehension
790 |
791 | - `{ }`: delimiter around iterable (curlybois for `dict` or `set`, `[` for list)
792 | - `a + b * i`: an expression (for instance, earlier when we made a list of odd numbers this
793 | expression was `2*k + 1`) to be evaluated for each item in source list.
794 | - `|`: `for`
795 | - `a,b ∈ ℝ`: this just shows that `a,b` are drawn from a particular place, in
796 | this case the real numbers.
797 |
798 | So if you've been writing Python listcomps, that definition of the complex
799 | numbers wasn't so bad! Say it with me this time
800 |
801 | `ℂ = {a + b*i | a,b ∈ ℝ}``
802 |
803 | **inhaaaaaaless** *unison* "C IS THE SET OF a + b*i FOR REAL NUMBERS a AND b"
804 |
805 | If you want, you can draw up a grainy picture of an *interval* of ℂ with `zip`
806 | and `np.linspace`, and of course list comprehension.
807 |
808 | ```python
809 | j = np.complex(0,1)
810 |
811 | R = np.linspace(-2, 2, 100)
812 |
813 | {a + b * j for a,b in zip(R, R)}
814 | # too much to print but try it yourself.
815 | ```
816 |
817 | ## functions
818 |
819 | [Functions](https://en.wikipedia.org/wiki/Function_%28mathematics%29) are fundamental features of mathematics, and the concept is fairly easy to translate into code.
820 |
821 | A **function** transforms an input into an output value. For example, the following is a function:
822 |
823 | 
824 |
825 |
826 |
827 | We can give this function a *name*. Commonly, we use `ƒ` to describe a function, but it could be named `A` or anything else.
828 |
829 | 
830 |
831 |
832 |
833 | In code, we might name it `square` and write it like this:
834 |
835 | ```python
836 | def square(x):
837 | return math.pow(x, 2)
838 |
839 | ```
840 |
841 | Sometimes a function is not named, and instead the output is written.
842 |
843 | 
844 |
845 |
846 |
847 | In the above example, *x* is the input, the transformation is *squaring*, and *y*
848 | is the output. We can express this as an equation because, conventionally, we
849 | think of *x* as input and *y* as output.
850 |
851 | But we have a stronger idea called **anonymous functions** to generalize this.
852 |
853 | Just as we can name strings `x = "Alonzo"` then call them with their names *or*
854 | we can just pass string *literals*, we also have **function literals**.
855 |
856 | Math first, then python:
857 |
858 | `x ↦ x^2` is equivalent to the equational description above.
859 |
860 | Nearly identical, but very different to the untrained eye, is `λx.x^2`, hence
861 | the python keyword
862 | ```python
863 | lambda x: x**2
864 | ```
865 |
866 | Functions can also have multiple parameters, like in a programming language. These are known as *arguments* in mathematics, and the number of arguments a function takes is known as the *arity* of the function.
867 |
868 | 
869 |
870 |
871 |
872 | ### dictionaries are functions
873 |
874 | Sometimes mathematicians, like software developers, need to specify *maps* by
875 | *enumerating each input-output pair** when there is no expression that computes
876 | output from input.
877 |
878 | **Note**: formally, mathematicians require that **functions not be ambiguous***,
879 | so when you have a function and you have an input, there can be no uncertainty
880 | as to what the output should be; you mustn't be confused about whether an apple
881 | is red or purple (in introductory algebra courses this is called
882 | the "vertical line test", but it applies to all maps). Notice that the
883 | implementation of hash maps already guarantees this in the case of dictionaries!
884 | Notice also that we make no such requirement on
885 | *outputs*, both an apple *and* a banana can land on purple! With caveats like
886 | these, we can [study the properties of different kinds of functions](https://en.wikipedia.org/wiki/Bijection,_injection_and_surjection)
887 | into different kinds, important in compression and security engineering.
888 |
889 | ### piecewise function
890 |
891 | Some functions will use different relationships depending on the input value, *x*.
892 |
893 | The following function *ƒ* chooses between two "sub functions" depending on the input value.
894 |
895 | 
896 |
897 |
902 |
903 | This is very similar to `if` / `else` in code. The right-side conditions are often written as **"for x < 0"** or **"if x = 0"**. If the condition is true, the function to the left is used.
904 |
905 | In piecewise functions, **"otherwise"** and **"elsewhere"** are analogous to the `else` statement in code.
906 |
907 | ```python
908 | def f(x):
909 | if (x >= 1):
910 | return (math.pow(x, 2) - x) / x
911 | else:
912 | return 0
913 |
914 | ```
915 |
916 | ### common functions
917 |
918 | There are some function names that are ubiquitous in mathematics. For a programmer, these might be analogous to functions "built-in" to the language (like `parseInt` in JavaScript).
919 |
920 | One such example is the *sgn* function. This is the *signum* or *sign* function. Let's use [piecewise function](#piecewise-function) notation to describe it:
921 |
922 | 
923 |
924 |
930 |
931 | In code, it might look like this:
932 |
933 | ```python
934 | def signum(x):
935 | if (x < 0):
936 | return -1
937 | elif (x > 0):
938 | return 1
939 | else:
940 | return 0
941 | ```
942 |
943 | See [signum](https://github.com/scijs/signum) for this function as a module.
944 |
945 | Other examples of such functions: *sin*, *cos*, *tan*.
946 |
947 | ### function notation
948 |
949 | In some literature, functions may be defined with more explicit notation. For example, let's go back to the `square` function we mentioned earlier:
950 |
951 | 
952 |
953 |
954 |
955 | It might also be written in the following form:
956 |
957 | 
958 |
959 |
960 |
961 | The arrow here with a tail typically means "maps to," as in *x maps to x2*.
962 |
963 | Sometimes, when it isn't obvious, the notation will also describe the *domain* and *codomain* of the function. A more formal definition of *ƒ* might be written as:
964 |
965 | 
966 |
967 |
972 |
973 | A function's *domain* and *codomain* is a bit like its *input* and *output* types, respectively. Here's another example, using our earlier *sgn* function, which outputs an integer:
974 |
975 | 
976 |
977 |
978 |
979 | The arrow here (without a tail) is used to map one *set* to another.
980 |
981 | In Python and other dynamically typed languages, you might use documentation and/or runtime checks to explain and validate a function's input/output. Example:
982 |
983 | ```python
984 | def square_ints(k):
985 | ''' FEED ME INTEGER '''
986 | try:
987 | assert isinstance(k, int), "I HUNGER FOR AN INTEGER! "
988 | return math.pow(k, 2)
989 | except AssertionError as e:
990 | raise e
991 | ```
992 |
993 | The python of a more glorious future as described in
994 | [pep484](https://www.python.org/dev/peps/pep-0484/) proposes a static type
995 | checker for Python, but no one's proposed anything shrewd enough to *prevent
996 | code with type errors from compiling* for Python yet.
997 |
998 | As we will see in the following sample of `pep484` Python, the set
999 | interpretation of domain and codomain makes way for a *types* interpretation of
1000 | domain and codomain
1001 |
1002 | ```python
1003 | def square(x: float) -> float:
1004 | ''' a pep484 annotation isn't that different from if i declared in the docstring;
1005 |
1006 | input/domain: a float
1007 | output/codomain: another float
1008 | '''
1009 | return x**2
1010 | ```
1011 |
1012 | Other languages, like Java, allow for true method overloading based on the
1013 | static types of a function's input/output. This is closer to mathematics: two
1014 | functions are not the same if they use a different *domain*. This is also called
1015 | *polymorphism* and it explains why `'literally' + 'alonzo'` concats two strings
1016 | together but `1 + 1` is addition on numbers.
1017 |
1018 | ## prime
1019 |
1020 | The prime symbol (`′`) is often used in variable names to describe things which are similar, without giving it a different name altogether. It can describe the "next value" after some transformation.
1021 |
1022 | For example, if we take a 2D point *(x, y)* and rotate it, you might name the result *(x′, y′)*. Or, the *transpose* of matrix **M** might be named **M′**.
1023 |
1024 | In code, we typically just assign the variable a more descriptive name, like `transformedPosition`.
1025 |
1026 | For a mathematical [function](#function), the prime symbol often describes the *derivative* of that function. Derivatives will be explained in a future section. Let's take our earlier function:
1027 |
1028 | 
1029 |
1030 |
1031 |
1032 | Its derivative could be written with a prime `′` symbol:
1033 |
1034 | 
1035 |
1036 |
1037 |
1038 | In code:
1039 |
1040 | ```python
1041 | def f(x):
1042 | return Math.pow(x, 2)
1043 |
1044 | def f_prime(x):
1045 | return 2 * x
1046 | ```
1047 |
1048 | Multiple prime symbols can be used to describe the second derivative *ƒ′′* and third derivative *ƒ′′′*. After this, authors typically express higher orders with roman numerals *ƒ*IV or superscript numbers *ƒ*(n).
1049 |
1050 | ## floor & ceiling
1051 |
1052 | The special brackets `⌊x⌋` and `⌈x⌉` represent the *floor* and *ceil* functions, respectively.
1053 |
1054 | 
1055 |
1056 |
1057 |
1058 | 
1059 |
1060 |
1061 |
1062 | In code:
1063 |
1064 | ```python
1065 | math.floor(4.8)
1066 | math.ceil(3.1)
1067 | np.floor(4.9)
1068 | np.ceil(3.001)
1069 | ```
1070 |
1071 | > **Note**: the Numpy version returns a float, in the above example `4.0`,
1072 | > rather than the int `4`
1073 |
1074 | When the two symbols are mixed `⌊x⌉`, it typically represents a function that rounds to the nearest integer:
1075 |
1076 | 
1077 |
1078 |
1079 |
1080 | Python automatically gives you a keyword `round` to call on a number.
1081 |
1082 | ## arrows
1083 |
1084 | Arrows are often used in [function notation](#function-notation). Here are a few other areas you might see them.
1085 |
1086 | #### material implication
1087 |
1088 | Arrows like `⇒` and `→` are sometimes used in logic for *material implication.* That is, if A is true, then B is also true.
1089 |
1090 | 
1091 |
1092 |
1093 |
1094 | Interpreting this as code might look like this:
1095 |
1096 | ```python
1097 | def if_A_then_B:
1098 | if A:
1099 | assert B, "alas, not A!"
1100 | return B
1101 | ```
1102 |
1103 | The arrows can go in either direction `⇐` `⇒`, or both `⇔`. When *A ⇒ B* and *B ⇒ A*, they are said to be equivalent:
1104 |
1105 | 
1106 |
1107 |
1108 |
1109 | #### inequality
1110 |
1111 | In math, the `<` `>` `≤` and `≥` are typically used in the same way we use them in code: *less than*, *greater than*, *less than or equal to* and *greater than or equal to*, respectively.
1112 |
1113 | ```python
1114 | assert 50 > 2
1115 | assert 2 < 10
1116 | assert 3 <= 4
1117 | assert 4 >= 4
1118 | ```
1119 |
1120 | On rare occasions you might see a slash through these symbols, to describe *not*. As in, *k* is "not greater than" *j*.
1121 |
1122 | 
1123 |
1124 |
1125 |
1126 | The `≪` and `≫` are sometimes used to represent *significant* inequality. That
1127 | is, *k* is an [order of
1128 | magnitude](https://en.wikipedia.org/wiki/Order_of_magnitude) larger than *j*.
1129 | Sometimes read "beats", when I say `x^k ≫ log(x)` what I'm really saying is that
1130 | "polynomial functions grow an order of magnitude faster than logarithms; in a
1131 | word, the polynomial *beats* the logarithm."
1132 |
1133 | 
1134 |
1135 |
1136 |
1137 | #### conjunction & disjunction
1138 |
1139 | Another use of arrows in logic is conjunction `∧` and disjunction `∨`. They are analogous to a programmer's `AND` and `OR` operators, respectively.
1140 |
1141 | The following shows conjunction `∧`, the logical `AND`.
1142 |
1143 | 
1144 |
1145 |
1146 |
1147 | In Python, we just say `and`. Assuming *k* is a natural number, the logic implies that *k* is 3:
1148 |
1149 | ```python
1150 | lambda k: if (k > 2 and k < 4): assert k == 3, "Exercise: can this error ever be raised?"
1151 | ```
1152 |
1153 | Since both sides are equivalent `⇔`, it also implies the following:
1154 |
1155 | ```python
1156 | lambda k: if (k == 3): assert (k > 2 and k < 4), "I mean it, think through this exercise."
1157 | ```
1158 |
1159 | The down arrow `∨` is logical disjunction, like the OR operator.
1160 |
1161 | 
1162 |
1163 |
1164 |
1165 | In Python, we have the `or` keyword. Like and, it is a function that will trade
1166 | you one bool for two bools.
1167 |
1168 | ## logical negation
1169 |
1170 | Occasionally, the `¬`, `~` and `!` symbols are used to represent logical `NOT`. For example, *¬A* is only true if A is false.
1171 |
1172 | Here is a simple example using the *not* symbol:
1173 |
1174 | 
1175 |
1176 |
1177 |
1178 | An example of how we might interpret this in code:
1179 |
1180 | ```python
1181 | lambda x, y: if (x != y): assert not x == y, "arrr, buried treasure lost forever. "
1182 | ```
1183 |
1184 | *Note:* The tilde `~` has many different meanings depending on context. For example, *row equivalence* (matrix theory) or *same order of magnitude* (discussed in [equality](#equality)).
1185 |
1186 | ## intervals
1187 |
1188 | Sometimes a function deals with real numbers restricted to some range of values, such a constraint can be represented using an *interval*
1189 |
1190 | For example we can represent the numbers between zero and one including/not including zero and/or one as:
1191 |
1192 | - Not including zero or one: 
1193 |
1194 |
1195 |
1196 | - Including zero or but not one: 
1197 |
1198 |
1199 |
1200 | - Not including zero but including one: 
1201 |
1202 |
1203 |
1204 | - Including zero and one: 
1205 |
1206 |
1207 |
1208 | For example we to indicate that a point `x` is in the unit cube in 3D we say:
1209 |
1210 | 
1211 |
1212 |
1213 |
1214 | In Python, we have to be sensitive about **inclusive vs. exclusive boundaries**
1215 | in generators like `range`, but you already know that.
1216 |
1217 | if you want to play with *infinite lists* in Python, learn more about [generators](https://jeffknupp.com/blog/2013/04/07/improve-your-python-yield-and-generators-explained/)
1218 |
1219 |
1220 | Intervals are used in conjunction with set operations:
1221 |
1222 | - *intersection* e.g. 
1223 |
1224 |
1225 |
1226 | - *union* e.g. 
1227 |
1228 |
1229 |
1230 | - *difference* e.g.  and 
1231 |
1232 |
1233 |
1234 |
1235 | Integer versions in basic python look like this
1236 |
1237 | ```python
1238 | # intersection of two int intervals
1239 | [x for x in range(3,5) if x in range(4, 6+1)]
1240 | # Out: [4]
1241 |
1242 | # Union of two int intervals
1243 | [x for x in range(20) if x in range(3, 5) or x in range(4, 6+1)]
1244 | # Out: [3, 4, 5, 6]
1245 |
1246 | # Set difference
1247 | [x for x in range(3, 5) if x not in range(4, 6+1)]
1248 | # Out: [3]
1249 |
1250 | [x for x in range(4, 6+1) if x not in range(3, 5)]
1251 | # Out: [5, 6]
1252 | ```
1253 |
1254 | Using `np.linspace`, we can approximate what the real versions would look like.
1255 |
1256 | ```python
1257 | R = np.linspace(-1, 9, 100)
1258 |
1259 | # intersection of two float intervals
1260 | [x for x in R if 3 <= x < 5 and 4 <= x <= 6]
1261 |
1262 | # Union of two float intervals
1263 | [x for x in R if 3 <= x < 5 or 4 <= x <= 6]
1264 |
1265 | # set differences of two float intervals.
1266 | [x for x in R if 3 <= x < 5 and not (4 <= x <= 6)]
1267 |
1268 | [x for x in R if 4 <= x <= 6 and not (3 <= x < 5)]
1269 | ```
1270 |
1271 | You should definitely run these in repl and try to wrap your head around them.
1272 |
1273 |
1274 |
1275 | ## more...
1276 |
1277 | Like this guide? Suggest some [more features](https://github.com/Jam3/math-as-code/issues/1) or send us a Pull Request!
1278 |
1279 | ## Contributing
1280 |
1281 | For details on how to contribute, see [CONTRIBUTING.md](./CONTRIBUTING.md).
1282 |
1283 | ## License
1284 |
1285 | MIT, see [LICENSE.md](http://github.com/Jam3/math-as-code/blob/master/LICENSE.md) for details.
1286 |
1287 | [1]: https://en.wikipedia.org/wiki/(%CE%B5,_%CE%B4)-definition_of_limit
1288 | [2]: http://mimosa-pudica.net/improved-oren-nayar.html#images
1289 | [3]: https://en.wikipedia.org/wiki/G%C3%B6del,_Escher,_Bach
1290 | [4]: http://buzzard.ups.edu/courses/2007spring/projects/million-paper.pdf
1291 | [5]: https://www.math.washington.edu/~morrow/464_12/fft.pdf
1292 |
--------------------------------------------------------------------------------
/README-zh.md:
--------------------------------------------------------------------------------
1 | # math-as-code
2 |
3 | > 译注:译者英文与数学水平都非常有限,尝试翻译,如有错误请指正。[英文原版](./README.md) 在此。
4 |
5 | 这是一份通过对比数学符号和JavaScript代码来帮助开发者更容易了解数学符号的参考。
6 |
7 | 动机:学术论文可能会吓着自学游戏和图形的程序猿:)
8 |
9 | 这个指南还没有完成。如果你发现错误或者想要贡献,请[open a ticket](https://github.com/Jam3/math-as-code/issues)或发一个 PR。
10 |
11 |
12 | > **注意**: 简洁起见,有些代码示例使用了[npm 包](https://www.npmjs.com/)。你可以到他们的GitHub repos来查看实现的详细情况。
13 |
14 | # 前言
15 |
16 | 数学符号可以表示不同的意思,这取决于作者,上下文和所学习的领域(线性代数,集合理论,等等)。这份指南也许不会涵盖符号的*所有*用法。在某些情况,会引用一些真实材料(博客文章,出版物等等)来演示某个符号的实际用法。
17 |
18 | 更完整的列表,请看[Wikipedia - List of Mathematical Symbols](https://en.wikipedia.org/wiki/List_of_mathematical_symbols)。
19 |
20 | 简单起见,这里许多的代码示例都操作浮点数值,并不是数字健壮的(numerically robust)。为什么这会是一个问题的更多细节请看[Robust Arithmetic Notes](https://github.com/mikolalysenko/robust-arithmetic-notes) 作者是 Mikola Lysenko。
21 |
22 | # 目录
23 |
24 | - [变量名约定](#变量名约定)
25 | - [等号 `=` `≈` `≠` `:=`](#等号)
26 | - [平方根与复数 `√` *`i`*](#平方根与复数)
27 | - [点 & 叉 `·` `×` `∘`](#点--叉)
28 | - [标量乘法](#标量乘法)
29 | - [向量乘法](#向量乘法)
30 | - [点乘](#点乘)
31 | - [叉乘](#叉乘)
32 | - [西格玛 `Σ`](#西格玛sigma) - *求和*
33 | - [大写 Pi `Π`](#大写-pi) - *序列的积*
34 | - [管道 `||`](#管道pipes)
35 | - [绝对值](#绝对值)
36 | - [欧几里得模](#欧几里得模)
37 | - [行列式](#行列式)
38 | - [帽子 **`â`**](#帽子) - *单位向量*
39 | - ["属于" `∈` `∉`](#属于)
40 | - [常见数字集 `ℝ` `ℤ` `ℚ` `ℕ`](#常见数字集)
41 | - [函数 `ƒ`](#函数)
42 | - [分段函数](#分段函数)
43 | - [通用函数](#通用函数)
44 | - [函数符号 `↦` `→`](#函数符号)
45 | - [撇号 `′`](#撇号prime)
46 | - [向下取整和向上取整(floor & ceiling) `⌊` `⌉`](#向下取整和向上取整floor--ceiling)
47 | - [箭头](#箭头)
48 | - [实质蕴含(material implication) `⇒` `→`](#实质蕴含material-implication)
49 | - [等式 `<` `≥` `≫`](#等式equality)
50 | - [与 & 或 `∧` `∨`](#与conjunction--或disjunction)
51 | - [逻辑非 `¬` `~` `!`](#逻辑非logical-negation)
52 | - [区间(intervals)](#区间intervals)
53 | - [更多...](#更多)
54 |
55 | ## 变量名约定
56 |
57 | 有很多命名约定取决于上下文和所学领域,他们并不太一致。然而在一些文献中你会发现变量名遵循一些模式,例如:
58 |
59 | - *s* - 斜体小写字母用做标量 (例如一个数字)
60 | - **x** - 粗体小写字母用做向量 (例如一个2D点)
61 | - **A** - 粗体大写字母用做矩阵 (例如一个3D变换)
62 | - *θ* - 斜体小写希腊字母用做常量和特殊变量 (例如 [欧拉角 *θ*, *theta*](https://en.wikipedia.org/wiki/Spherical_coordinate_system))
63 |
64 | 本指南也基于这个格式。
65 |
66 | ## 等号
67 |
68 | 有很多符号很像等号 `=` 。这里有些常见的例子:
69 |
70 | - `=` 表示相等 (值相同)
71 | - `≠` 表示不相等 (值不同)
72 | - `≈` 表示约等于 (`π ≈ 3.14159`)
73 | - `:=` 表示定义 (A 被定义为 B)
74 |
75 | 在 JavaScript 中:
76 |
77 | ```js
78 | // 相等
79 | 2 === 3
80 |
81 | // 不相等
82 | 2 !== 3
83 |
84 | // 约等于
85 | almostEqual(Math.PI, 3.14159, 1e-5)
86 |
87 | function almostEqual(a, b, epsilon) {
88 | return Math.abs(a - b) <= epsilon
89 | }
90 | ```
91 |
92 | 你也许看过 `:=`, `=:` 和 `=` 符号用来表示 *定义*。[1]
93 |
94 | 例如,下边定义 *x* 为 2*kj* 的别名。
95 |
96 | 
97 |
98 |
99 |
100 | 在 JavaScript 中,我们用 `var` 来 *定义* 变量和提供别名:
101 |
102 | ```js
103 | var x = 2 * k * j
104 | ```
105 |
106 | 然而,这里的x值是可变的,仅是当时的一个快照。在某些有预处理器语言中的 `#define` 语句才比较接近于数学中的 *定义*。
107 |
108 | 在JavaScript (ES6) 中,更精确的 *定义* ,应该有点类似这样:
109 |
110 | ```js
111 | const f = (k, j) => 2 * k * j
112 | ```
113 |
114 | 与此不同的是,下边这句表示的是相等:
115 |
116 | 
117 |
118 |
119 |
120 | 上边的等式也可以解释为一个 [断言](https://developer.mozilla.org/en-US/docs/Web/API/console/assert):
121 |
122 | ```js
123 | console.assert(x === (2 * k * j))
124 | ```
125 |
126 | ## 平方根与复数
127 |
128 | 一个平方根运算是这种形式:
129 |
130 | 
131 |
132 |
133 |
134 | 在编程语言中我们使用 `sqrt` 函数, 像这样:
135 |
136 | ```js
137 | var x = 9;
138 | console.log(Math.sqrt(x));
139 | //=> 3
140 | ```
141 |
142 | 复数是  形式的表达式, 其中  是实数部分,  是虚数部分。 虚数  的定义为:
143 |
144 | .
145 |
146 |
147 | JavaScript没有内置复数的功能,但有一些库支持复数算法。例如, [mathjs](https://www.npmjs.com/package/mathjs):
148 |
149 | ```js
150 | var math = require('mathjs')
151 |
152 | var a = math.complex(3, -1)
153 | //=> { re: 3, im: -1 }
154 |
155 | var b = math.sqrt(-1)
156 | //=> { re: 0, im: -1 }
157 |
158 | console.log(math.multiply(a, b).toString())
159 | //=> '1 + 3i'
160 | ```
161 |
162 | 这个库还支持字符串表达式求值, 所以上边的可以写为:
163 |
164 | ```js
165 | console.log(math.eval('(3 - i) * i').toString())
166 | //=> '1 + 3i'
167 | ```
168 |
169 | 其他实现:
170 |
171 | - [immutable-complex](https://www.npmjs.com/package/immutable-complex)
172 | - [complex-js](https://www.npmjs.com/package/complex-js)
173 | - [Numeric-js](http://www.numericjs.com/)
174 |
175 | ## 点 & 叉
176 |
177 | 点 `·` 和叉 `×` 符号根据上下文的不同有不同的用法。
178 |
179 | 他们可能看上去很明显,但在进入下一部分之前,理解他们之间微妙的不同是非常重要的。
180 |
181 | #### 标量乘法
182 |
183 | 两个符号都可以表示简单的标量之间的乘法。下边的写法意思相同:
184 |
185 | 
186 |
187 |
188 |
189 | 在编程语言中,我们倾向用星号表示相乘:
190 |
191 | ```js
192 | var result = 5 * 4
193 | ```
194 |
195 | 通常,使用乘法符号只是为了避免意义模糊(例如两个数字之间的)。这里,我们可以完全省略:
196 |
197 | 
198 |
199 |
200 |
201 | 如果这些变量表示的是标量,则代码应该这样写:
202 |
203 | ```js
204 | var result = 3 * k * j
205 | ```
206 |
207 | #### 向量乘法
208 |
209 | 表示向量和标量之间相乘,或两向量的逐元素相乘(element-wise multiplication),我们不用点 `·` 或叉 `×` 符号。 这些符号在线性代数中有不同的意思,后边讨论。
210 |
211 | 让我们用之前的例子,但用在向量上。对于向量的逐元素相乘(element-wise vector multiplication)来说,你可能会看到用一个空心点来表示 [Hadamard product](https://en.wikipedia.org/wiki/Hadamard_product_%28matrices%29)。[2]
212 |
213 | 
214 |
215 |
216 |
217 | 某些时候,作者可能会显式定义一个不同的符号,例如圆中点 `⊙` 或实心圈 `●` 。[3]
218 |
219 | 这是对应的代码,使用数组 `[x, y]` 来表示2D向量。
220 |
221 | ```js
222 | var s = 3
223 | var k = [ 1, 2 ]
224 | var j = [ 2, 3 ]
225 |
226 | var tmp = multiply(k, j)
227 | var result = multiplyScalar(tmp, s)
228 | //=> [ 6, 18 ]
229 | ```
230 |
231 | `multiply` 和 `multiplyScalar` 函数应该这样:
232 |
233 | ```js
234 | function multiply(a, b) {
235 | return [ a[0] * b[0], a[1] * b[1] ]
236 | }
237 |
238 | function multiplyScalar(a, scalar) {
239 | return [ a[0] * scalar, a[1] * scalar ]
240 | }
241 | ```
242 |
243 | 同样的,矩阵相乘也不用 `·` 或 `×` 符号。 矩阵乘法会在后边章节提到.
244 |
245 | #### 点乘
246 |
247 | 点符号 `·` 可用来表示两向量之间的 [*点乘*](https://en.wikipedia.org/wiki/Dot_product) 。 由于其值是一个标量,通常被叫做 *标量积(scalar product)* 。
248 |
249 | 
250 |
251 |
252 |
253 | 这在线性代数和3D向量中是非常常见的,代码类似这样:
254 |
255 | ```js
256 | var k = [ 0, 1, 0 ]
257 | var j = [ 1, 0, 0 ]
258 |
259 | var d = dot(k, j)
260 | //=> 0
261 | ```
262 |
263 | 结果为 `0` 告诉我们两向量互相垂直. 这是3元素向量的 `点乘` 函数:
264 |
265 | ```js
266 | function dot(a, b) {
267 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
268 | }
269 | ```
270 |
271 | #### 叉乘
272 |
273 | 叉乘符号 `×` 可以用来表示两向量的 [*叉乘*](https://en.wikipedia.org/wiki/Cross_product)。
274 |
275 | 
276 |
277 |
278 |
279 | 在代码中,应该是这样:
280 |
281 | ```js
282 | var k = [ 0, 1, 0 ]
283 | var j = [ 1, 0, 0 ]
284 |
285 | var result = cross(k, j)
286 | //=> [ 0, 0, -1 ]
287 | ```
288 |
289 | 这里得到结果为 `[ 0, 0, -1 ]`,这个向量同时垂直于 **k** 和 **j** 。
290 |
291 | 我们的叉乘 `cross` 函数:
292 |
293 | ```js
294 | function cross(a, b) {
295 | var ax = a[0], ay = a[1], az = a[2],
296 | bx = b[0], by = b[1], bz = b[2]
297 |
298 | var rx = ay * bz - az * by
299 | var ry = az * bx - ax * bz
300 | var rz = ax * by - ay * bx
301 | return [ rx, ry, rz ]
302 | }
303 | ```
304 |
305 | 向量乘法,叉乘,点乘的其他实现:
306 |
307 | - [gl-vec3](https://github.com/stackgl/gl-vec3)
308 | - [gl-vec2](https://github.com/stackgl/gl-vec2)
309 | - [vectors](https://github.com/hughsk/vectors) - 包含 n维实现
310 |
311 | ## 西格玛(sigma)
312 |
313 | 大写希腊字母 `Σ` (Sigma) 用来表示 [总和 Summation](https://en.wikipedia.org/wiki/Summation)。 换句话说就是对一些数字求和。
314 |
315 | 
316 |
317 |
318 |
319 | 这里, `i=1` 是说从 `1` 西格玛上边的数字`100`为止。这些分别为上下边界。 "E" 右边的 *i* 告诉我们求和的是什么。代码:
320 |
321 | ```js
322 | var sum = 0
323 | for (var i = 1; i <= 100; i++) {
324 | sum += i
325 | }
326 | ```
327 |
328 | `sum` 的结果为 `5050` 。
329 |
330 | **提示:** 对于整数,这个特殊形式可以优化为:
331 |
332 | ```js
333 | var n = 100 // 上边界
334 | var sum = (n * (n + 1)) / 2
335 | ```
336 |
337 | 这里有另一个例子,这里的 *i* ,或 “想要求和的东西” 是不同的:
338 |
339 | 
340 |
341 |
342 |
343 | 代码:
344 |
345 | ```js
346 | var sum = 0
347 | for (var i = 1; i <= 100; i++) {
348 | sum += (2 * i + 1)
349 | }
350 | ```
351 |
352 | `sum` 的结果为 `10200` 。
353 |
354 | 这个符号可被嵌套,非常像嵌套一个 `for` 循环。 你应该先求和最右边的西格玛, 除非作者加入括号改变了顺序。然而下边的例子,由于我们处理有限的和,顺序就不重要了。
355 |
356 | 
357 |
358 |
359 |
360 | 代码:
361 |
362 | ```js
363 | var sum = 0
364 | for (var i = 1; i <= 2; i++) {
365 | for (var j = 4; j <= 6; j++) {
366 | sum += (3 * i * j)
367 | }
368 | }
369 | ```
370 |
371 | 这里,`sum` 值为 `135`。
372 |
373 | ## 大写 Pi
374 |
375 | 大写 Pi 或 “大Pi” 与 [西格玛](#西格玛sigma) 非常接近, 不同的是我们用乘法取得一系列数字的乘积。
376 |
377 | 看下边:
378 |
379 | 
380 |
381 |
382 |
383 | 代码应该类似这样:
384 |
385 | ```js
386 | var value = 1
387 | for (var i = 1; i <= 6; i++) {
388 | value *= i
389 | }
390 | ```
391 |
392 | `value` 结果应得到 `720`。
393 |
394 | ## 管道(pipes)
395 |
396 | 管道符号,就是 *竖线(bars)*,根据上下文不同,可以表示不同意思。下边的是3种常见用途 [绝对值](#绝对值), [欧几里得模](#欧几里得模), 和 [行列式](#行列式)。
397 |
398 | 这3种特性都是描述对象的 *长度(length)* 。
399 |
400 | #### 绝对值
401 |
402 | 
403 |
404 |
405 |
406 | 对于数字 *x*, `|x|` 表示 *x* 的绝对值。代码为:
407 |
408 | ```js
409 | var x = -5
410 | var result = Math.abs(x)
411 | // => 5
412 | ```
413 |
414 | #### 欧几里得模(Euclidean norm)
415 |
416 | 
417 |
418 |
419 |
420 | 对于向量 **v**, `‖v‖` 是 **v** 的[欧几里得模(Euclidean norm)](https://en.wikipedia.org/wiki/Norm_%28mathematics%29#Euclidean_norm) 。也叫做向量的 "量级(magnitude)" 或 "长度(length)" 。
421 |
422 | 通常用双竖线表示来避免与*绝对值* 符号混淆,但有些时候也会看见单竖线。
423 |
424 | 
425 |
426 |
427 |
428 | 这里的例子用数组 `[x, y, z]` 来表示一个3D向量。
429 |
430 | ```js
431 | var v = [ 0, 4, -3 ]
432 | length(v)
433 | //=> 5
434 | ```
435 |
436 | `length` 函数:
437 |
438 | ```js
439 | function length (vec) {
440 | var x = vec[0]
441 | var y = vec[1]
442 | var z = vec[2]
443 | return Math.sqrt(x * x + y * y + z * z)
444 | }
445 | ```
446 |
447 | 其他实现:
448 |
449 | - [magnitude](https://github.com/mattdesl/magnitude/blob/864ff5a7eb763d34bf154ac5f5332d7601192b70/index.js) - n-dimensional
450 | - [gl-vec2/length](https://github.com/stackgl/gl-vec2/blob/21f460a371540258521fd2f720d80f14e87bd400/length.js) - 2D vector
451 | - [gl-vec3/length](https://github.com/stackgl/gl-vec3/blob/507480fa57ba7c5fb70679cf531175a52c48cf53/length.js) - 3D vector
452 |
453 | #### 行列式
454 |
455 | 
456 |
457 |
458 |
459 | 对于一个矩阵 **A**, `|A|` 表示矩阵 **A** 的[行列式(determinant)](https://en.wikipedia.org/wiki/Determinant)。
460 |
461 | 这是一个计算 2x2 矩阵行列式的例子,矩阵用一个column-major格式的扁平数数组表示。
462 |
463 | ```js
464 | var determinant = require('gl-mat2/determinant')
465 |
466 | var matrix = [ 1, 0, 0, 1 ]
467 | var det = determinant(matrix)
468 | //=> 1
469 | ```
470 |
471 | 实现:
472 |
473 | - [gl-mat4/determinant](https://github.com/stackgl/gl-mat4/blob/c2e2de728fe7eba592f74cd02266100cc21ec89a/determinant.js) - 也可以看 [gl-mat3](https://github.com/stackgl/gl-mat3) 和 [gl-mat2](https://github.com/stackgl/gl-mat2)
474 | - [ndarray-determinant](https://www.npmjs.com/package/ndarray-determinant)
475 | - [glsl-determinant](https://www.npmjs.com/package/glsl-determinant)
476 | - [robust-determinant](https://www.npmjs.com/package/robust-determinant)
477 | - [robust-determinant-2](https://www.npmjs.com/package/robust-determinant-2) 和 [robust-determinant-3](https://www.npmjs.com/package/robust-determinant-3),专门 2x2 和 3x3 的矩阵
478 |
479 | ## 帽子
480 |
481 | 在几何里,字母上的 “帽子” 符号用来表示一个[单位向量](https://en.wikipedia.org/wiki/Unit_vector)。例如,这是向量 **a** 的单位向量。
482 |
483 | 
484 |
485 |
486 |
487 | 在笛卡尔空间中,单位向量的长度为1。意思是向量的每个部分都在 -1.0 到 1.0 之间。这里我们 *归一化(normalize)* 一个3D向量为单位向量。
488 |
489 | ```js
490 | var a = [ 0, 4, -3 ]
491 | normalize(a)
492 | //=> [ 0, 0.8, -0.6 ]
493 | ```
494 |
495 | 这是 `归一化(normalize)` 函数,接收一个3D向量参数:
496 |
497 | ```js
498 | function normalize(vec) {
499 | var x = vec[0]
500 | var y = vec[1]
501 | var z = vec[2]
502 | var squaredLength = x * x + y * y + z * z
503 |
504 | if (squaredLength > 0) {
505 | var length = Math.sqrt(squaredLength)
506 | vec[0] = vec[0] / length
507 | vec[1] = vec[1] / length
508 | vec[2] = vec[2] / length
509 | }
510 | return vec
511 | }
512 | ```
513 |
514 | 其他实现:
515 |
516 | - [gl-vec3/normalize](https://github.com/stackgl/gl-vec3/blob/507480fa57ba7c5fb70679cf531175a52c48cf53/normalize.js) 和 [gl-vec2/normalize](https://github.com/stackgl/gl-vec2/blob/21f460a371540258521fd2f720d80f14e87bd400/normalize.js)
517 | - [vectors/normalize-nd](https://github.com/hughsk/vectors/blob/master/normalize-nd.js) (n-dimensional)
518 |
519 | ## 属于
520 |
521 | 集合理论中,“属于”符号 `∈` 和 `∋` 可以被用来描述某物是否为集合中的一个元素。例如:
522 |
523 | 
524 |
525 |
526 |
527 | 这里我们有一个数字集 *A* `{ 3, 9, 14 }` 而且我们说 `3` 是“属于”这个集合的。
528 |
529 | 在ES5种一个简单的实现应该这样:
530 |
531 | ```js
532 | var A = [ 3, 9, 14 ]
533 |
534 | A.indexOf(3) >= 0
535 | //=> true
536 | ```
537 |
538 | 然而,可以用只能保存唯一值的`Set`,这样更精确。这是ES6的一个特性。
539 |
540 | ```js
541 | var A = new Set([ 3, 9, 14 ])
542 |
543 | A.has(3)
544 | //=> true
545 | ```
546 |
547 | 反向的 `∋` 意义相同,只是顺序改变:
548 |
549 | 
550 |
551 |
552 |
553 | 你可以使用 "不属于" 符号 `∉` 和 `∌` 像这样:
554 |
555 | 
556 |
557 |
558 |
559 | ## 常见数字集
560 |
561 | 你可能在一些公式中看见一些大[黑板粗体字](https://en.wikipedia.org/wiki/Blackboard_bold)。他们一般是用来描述集合的。
562 |
563 | 例如,我们可以描述 *k* 是[属于](#属于) `ℝ` 集的一个元素。
564 |
565 | 
566 |
567 |
568 |
569 | 下边列出一些常见集和他们的符号。
570 |
571 | #### `ℝ` 实数(real numbers)
572 |
573 | 大 `ℝ` 描述 *实数(real numbers)* 的集合。他们包括整数,有理数,无理数。
574 |
575 | JavaScript认为整数和浮点数为相同类型,所以下边将是一个 *k* ∈ ℝ 的简单测试:
576 |
577 | ```js
578 | function isReal (k) {
579 | return typeof k === 'number' && isFinite(k);
580 | }
581 | ```
582 |
583 | *注意:* 实数也是 *有限数(finite)*,*非无限的(not infinite)*
584 |
585 | #### `ℚ` 有理数(rational numbers)
586 |
587 | 有理数是可以被表示为分数,或 *比率*(类似`⅗`)的实数。有理数不能以0作分母。
588 |
589 | 这意味着所有的整数都是有理数,因为可以看成分母为1。
590 |
591 | 换句话说无理数就是不能表示为比率的数,例如 π (PI)。
592 |
593 | #### `ℤ` 整数(integers)
594 |
595 | 一个整数,是没有小数部分的实数。可为正也可以为负。
596 |
597 | 在JavaScript中的简单测试应该这样:
598 |
599 | ```js
600 | function isInteger (n) {
601 | return typeof n === 'number' && n % 1 === 0
602 | }
603 | ```
604 |
605 | #### `ℕ` 自然数(natural numbers)
606 |
607 | 自然数是正整数或非负整数。取决于所学领域和上下文,集合中可能包含也可能不包含0,所以可以是下边任意一种集合。
608 |
609 | ```js
610 | { 0, 1, 2, 3, ... }
611 | { 1, 2, 3, 4, ... }
612 | ```
613 |
614 | 前者在计算机科学中更常见,例如:
615 |
616 | ```js
617 | function isNaturalNumber (n) {
618 | return isInteger(n) && n >= 0
619 | }
620 | ```
621 |
622 | #### `ℂ` 复数
623 |
624 | 复数是实数与虚数的组合,被视为2D平面上的一个坐标。更详细的信息请看[A Visual, Intuitive Guide to Imaginary Numbers](http://betterexplained.com/articles/a-visual-intuitive-guide-to-imaginary-numbers/)。
625 |
626 | ## 函数
627 |
628 | [函数](https://en.wikipedia.org/wiki/Function_%28mathematics%29) 是数学的基本特性,其概念很容易转换成代码。
629 |
630 | 函数把输入输出值联系起来。例如下边是一个函数:
631 |
632 | 
633 |
634 |
635 |
636 | 我们可以给函数一个 *名字* 。一般来说我们用 `ƒ` 来描述一个函数,但也可以命名为 `A(x)` 或其他什么。
637 |
638 | 
639 |
640 |
641 |
642 | 在代码中,我们可以给函数命名为 `square` 写出来应该类似这样:
643 |
644 | ```js
645 | function square (x) {
646 | return Math.pow(x, 2)
647 | }
648 | ```
649 |
650 | 有时函数没有名字,而是直接写出输出值。
651 |
652 | 
653 |
654 |
655 |
656 | 在上边的例子中,*x* 是输入值,*y* 是输出值,他们是平方的关系。
657 |
658 | 像编程语言一样,函数也可以有多个参数。他们在数学中被称为 *arguments*,并且函数接受的参数数量被称为函数的 *arity* 。
659 |
660 | 
661 |
662 |
663 |
664 | 代码:
665 |
666 | ```js
667 | function length (x, y) {
668 | return Math.sqrt(x * x + y * y)
669 | }
670 | ```
671 |
672 | ### 分段函数
673 |
674 | 有些函数根据输入值 *x* 的不同会有不同的关系。
675 |
676 | 下边的函数 *f* 根据不同的输入值选择两个不同的“子函数”。
677 |
678 | 
679 |
680 |
685 |
686 | 这非常接近于代码中的`if` / `else`。右边的条件经常被写为**"for x < 0"** 或 **"if x = 0"**。如果条件为true,就使用其左边的函数。
687 |
688 | 在分段函数中,**"otherwise"** 和 **"elsewhere"** 类似于代码中的 `else` 。
689 |
690 | ```js
691 | function f (x) {
692 | if (x >= 1) {
693 | return (Math.pow(x, 2) - x) / x
694 | } else {
695 | return 0
696 | }
697 | }
698 | ```
699 |
700 | ### 通用函数
701 |
702 | 有些函数名在数学中是普遍存在的。在一个程序员的角度看,这些应该类似于编程语言中的“内置”函数(就像JavaScript中的 `parseInt` )。
703 |
704 | 一个例子就是 *sgn* 函数。这是 *正负号* 函数,或者叫 *符号* 函数。让我们用[分段函数](#分段函数)来描述它:
705 |
706 | 
707 |
708 |
714 |
715 | 代码中,应该这样:
716 |
717 | ```js
718 | function sgn (x) {
719 | if (x < 0) return -1
720 | if (x > 0) return 1
721 | return 0
722 | }
723 | ```
724 |
725 | 此函数作为独立的module在这里[signum](https://github.com/scijs/signum)。
726 |
727 | 其他类似函数的例子还有: *sin*, *cos*, *tan*。
728 |
729 | ### 函数符号
730 |
731 | 在某些著作中,函数可以被更明确的符号定义。例如,让我们回到之前提到的 `square` 函数。
732 |
733 | 
734 |
735 |
736 |
737 | 也可以写为以下形式:
738 |
739 | 
740 |
741 |
742 |
743 | 带尾巴的箭头通常意思为“映射到”,如,*将x映射到x2*
744 |
745 | 有时,不是很常见,这个符号也用来描述函数的 *domain* 和 *codomain*。对 *ƒ* 更正式的定义可以写为:
746 |
747 | 
748 |
749 |
754 |
755 | 函数的 *domain* 和 *codomain* 分别跟他的 *input* 和 *output* 类型有点像。这里有另一个例子,使用了我们之前输出整数的 *sgn* 函数。
756 |
757 | 
758 |
759 |
760 |
761 | 这里的箭头(没有尾巴)用来映射一个 *集合* 到另一个。
762 |
763 | 在JavaScript和其他动态类型语言中,你也许会用文档 和/或 运行时检查来解释和验证函数的输入/输出。例子:
764 |
765 | ```js
766 | /**
767 | * Squares a number.
768 | * @param {Number} a real number
769 | * @return {Number} a real number
770 | */
771 | function square (a) {
772 | if (typeof a !== 'number') {
773 | throw new TypeError('expected a number')
774 | }
775 | return Math.pow(a, 2)
776 | }
777 | ```
778 |
779 | 有些工具例如[flowtype](http://flowtype.org/)尝试将静态类型带入到JavaScript中。
780 |
781 | 其他语言,例如Java,允许真正的方法重载(overloading),它们基于函数输入输出的静态类型。这更接近于数学领域:使用不同 *domain* 的两个函数是不同的。
782 |
783 | ## 撇号(prime)
784 |
785 | 撇号 (`′`) 通常用在变量名上,用来描述某物很类似,而不用另起个名来描述它。也可以描述经过一些变换后的“下一个值”。
786 |
787 | 例如,如果我们有一个2D点 *(x, y)* ,然后旋转它,你会把旋转后的点命名为*(x′, y′)*。 或者将矩阵 **M** 的 *转置矩阵* 命名为 **M′**。
788 |
789 | 在代码中,我们通常的分配一个描述更详细的变量名,例如`transformedPosition`。
790 |
791 | 对于一个[函数](#函数),撇号通常描述为函数的 *导函数(derivative)* 。导函数会在未来的章节解释。我们来看一个之前的函数:
792 |
793 | 
794 |
795 |
796 |
797 | 它的导函数(derivative)可以写为一个带撇号`′`的函数:
798 |
799 | 
800 |
801 |
802 |
803 | 代码:
804 |
805 | ```js
806 | function f (x) {
807 | return Math.pow(x, 2)
808 | }
809 |
810 | function fPrime (x) {
811 | return 2 * x
812 | }
813 | ```
814 |
815 | 使用多个撇号可以用来表示 二阶导函数(derivative) *ƒ′′* 或 三阶导函数(derivative)*ƒ′′′* ,之后更高的数字,一般作者会用罗马数字 *ƒ*IV 或上标数字 *ƒ*(n) 表示。
816 |
817 | ## 向下取整和向上取整(floor & ceiling)
818 |
819 | `⌊x⌋` 和 `⌈x⌉` 这种特殊的括号分别用来表示*floor* 和 *ceil* 函数。
820 |
821 | 
822 |
823 |
824 |
825 | 
826 |
827 |
828 |
829 | 代码:
830 |
831 | ```js
832 | Math.floor(x)
833 | Math.ceil(x)
834 | ```
835 |
836 | 当这两个符号混合`⌊x⌉`,它通常表示一个取整到最近的整数的函数。
837 |
838 | 
839 |
840 |
841 |
842 | 代码:
843 |
844 | ```js
845 | Math.round(x)
846 | ```
847 |
848 | ## 箭头
849 |
850 | 箭头通常用来表示[函数符号](#函数符号)。这里还有一些在其他领域中的用法可以看看。
851 |
852 | #### 实质蕴含(material implication)
853 |
854 | `⇒` 和 `→` 优势被用作表示实质蕴涵(material implication)的逻辑。意思是如果A是true,那么B也是true。
855 |
856 | 
857 |
858 |
859 |
860 | 解释为代码应该为:
861 |
862 | ```js
863 | if (A === true) {
864 | console.assert(B === true)
865 | }
866 | ```
867 |
868 | 箭头可以是左右任何方向 `⇐` `⇒`,也可以双向`⇔`。当 *A ⇒ B* 并且 *B ⇒ A*,就是他们是相等的:
869 |
870 | 
871 |
872 |
873 |
874 | #### 等式(equality)
875 |
876 | 在数学中, `<` `>` `≤` 和 `≥` 与代码中的使用方法一样:分别为 *小于*, *大于*, *小于等于* 和 *大于等于*。
877 |
878 | ```js
879 | 50 > 2 === true
880 | 2 < 10 === true
881 | 3 <= 4 === true
882 | 4 >= 4 === true
883 | ```
884 |
885 | 偶尔会看到在这些符号上加了一条斜线,来表示 *不*,比如, *k* 不 "大于" *j*.
886 |
887 | 
888 |
889 |
890 |
891 | `≪` 和 `≫`通常用来表示 *明显(significant)* 不相等。这是说 *k* 是有[数量级(order of magnitude)](https://en.wikipedia.org/wiki/Order_of_magnitude)的大于 *j*。
892 |
893 | 
894 |
895 |
896 |
897 | 在数学中,*数量级(order of magnitude)* 是相当明确的;不只是“相当大的不同”而已。上边的一个简单例子:
898 |
899 | ```js
900 | orderOfMagnitude(k) > orderOfMagnitude(j)
901 | ```
902 |
903 | 下边是我们的 `orderOfMagnitude` 函数,使用了[Math.trunc](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc) (ES6)。
904 |
905 | ```js
906 | function log10(n) {
907 | // logarithm in base 10
908 | return Math.log(n) / Math.LN10
909 | }
910 |
911 | function orderOfMagnitude (n) {
912 | return Math.trunc(log10(n))
913 | }
914 | ```
915 |
916 | *Note:* This is not numerically robust.
917 |
918 | 这里是在ES5下使用[math-trunc](https://www.npmjs.com/package/math-trunc) 的polyfill。
919 |
920 | #### 与(conjunction) & 或(disjunction)
921 |
922 | 另一种箭头在逻辑中的使用是与(conjunction)`∧` 和 或(disjunction) `∨`。他们分别类似于程序员的 `AND` 和 `OR`操作。
923 |
924 | 下边展示了与(conjunction)`∧`, 逻辑中的`AND`.
925 |
926 | 
927 |
928 |
929 |
930 | 在JavaScript中,我们使用 `&&` 假设 *k* 是一个自然数,那么这个逻辑意味着k等于3:
931 |
932 | ```js
933 | if (k > 2 && k < 4) {
934 | console.assert(k === 3)
935 | }
936 | ```
937 |
938 | 由于双边都相等 `⇔`,所以也说明下边成立:
939 |
940 | ```js
941 | if (k === 3) {
942 | console.assert(k > 2 && k < 4)
943 | }
944 | ```
945 |
946 | 下箭头 `∨` 是逻辑或(disjunction),就像 OR 操作符一样。
947 |
948 | 
949 |
950 |
951 |
952 | 代码:
953 |
954 | ```js
955 | A || B
956 | ```
957 |
958 | ## 逻辑非(logical negation)
959 |
960 | 有时候,`¬`, `~` 和 `!` 符号都用来表示逻辑 `NOT`。例如,只有在A为false的时候,*¬A* 为true。
961 |
962 | 这里是一个使用 *not* 符号简单的例子:
963 |
964 | 
965 |
966 |
967 |
968 | 翻译成代码的例子:
969 |
970 | ```js
971 | if (x !== y) {
972 | console.assert(!(x === y))
973 | }
974 | ```
975 |
976 | *注意:* 根据上下文的不同,波浪线 `~` 可以有很多种不同的意思。例如,*行等价(row equivalence)*(矩阵理论)或*相同数量级(same order of magnitude)* (在[等式(equality)](#等式equality)章节讨论过)。
977 |
978 | ## 区间(intervals)
979 |
980 | 有时函数会处理被一些值限定范围的实数,这样的约束可以用*区间(interval)*来表示。
981 |
982 | 例如我们可以表示0和1之间的数,让他们包含或不包含0和1:
983 |
984 | - 不包含0或1: 
985 |
986 |
987 |
988 | - 包含0但不包含1: 
989 |
990 |
991 |
992 | - 不包含0但包含1: 
993 |
994 |
995 |
996 | - 包含0和1: 
997 |
998 |
999 |
1000 | 例如我们指出一个点 `x` 在3D单位立方体中,我们可以说:
1001 |
1002 | 
1003 |
1004 |
1005 |
1006 | 在代码中我们可以用两个元素大小的一维数组表示区间:
1007 |
1008 | ```js
1009 | var nextafter = require('nextafter')
1010 |
1011 | var a = [nextafter(0, Infinity), nextafter(1, -Infinity)] // 开区间
1012 | var b = [nextafter(0, Infinity), 1] // 左闭右开区间
1013 | var c = [0, nextafter(1, -Infinity)] // 左开右闭区间
1014 | var d = [0, 1] // 闭区间
1015 | ```
1016 |
1017 | 区间与集合运算结合符使用:
1018 |
1019 | - *交集(intersection)* e.g. 
1020 |
1021 |
1022 |
1023 | - *并集(union)* e.g. 
1024 |
1025 |
1026 |
1027 | - *差集(difference)* e.g.  还有 
1028 |
1029 |
1030 |
1031 |
1032 | 代码:
1033 |
1034 | ```js
1035 | var Interval = require('interval-arithmetic')
1036 | var nextafter = require('nextafter')
1037 |
1038 | var a = Interval(3, nextafter(5, -Infinity))
1039 | var b = Interval(4, 6)
1040 |
1041 | Interval.intersection(a, b)
1042 | // {lo: 4, hi: 4.999999999999999}
1043 |
1044 | Interval.union(a, b)
1045 | // {lo: 3, hi: 6}
1046 |
1047 | Interval.difference(a, b)
1048 | // {lo: 3, hi: 3.9999999999999996}
1049 |
1050 | Interval.difference(b, a)
1051 | // {lo: 5, hi: 6}
1052 | ```
1053 |
1054 | 见:
1055 |
1056 | - [next-after](https://github.com/scijs/nextafter)
1057 | - [interval-arithmetic](https://github.com/maurizzzio/interval-arithmetic)
1058 |
1059 | ## 更多...
1060 |
1061 | 喜欢这份指南?提出[更多的特性](https://github.com/Jam3/math-as-code/issues/1)的建议或给我们发Pull Request!
1062 |
1063 | ## 贡献
1064 |
1065 | 关于怎样贡献详见 [CONTRIBUTING.md](./CONTRIBUTING.md)。
1066 |
1067 | ## License
1068 |
1069 | MIT, 详见 [LICENSE.md](http://github.com/Jam3/math-as-code/blob/master/LICENSE.md)。
1070 |
1071 | [1]: http://mimosa-pudica.net/improved-oren-nayar.html#images
1072 | [2]: http://buzzard.ups.edu/courses/2007spring/projects/million-paper.pdf
1073 | [3]: https://www.math.washington.edu/~morrow/464_12/fft.pdf
1074 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # math-as-code
2 |
3 | >[Chinese translation (中文版)](./README-zh.md)
4 | >[Python version (English)](./PYTHON-README.md)
5 |
6 | This is a reference to ease developers into mathematical notation by showing comparisons with JavaScript code.
7 |
8 | Motivation: Academic papers can be intimidating for self-taught game and graphics programmers. :)
9 |
10 | This guide is not yet finished. If you see errors or want to contribute, please [open a ticket](https://github.com/Jam3/math-as-code/issues) or send a PR.
11 |
12 | > **Note**: For brevity, some code examples make use of [npm packages](https://www.npmjs.com/). You can refer to their GitHub repos for implementation details.
13 |
14 |
15 |
16 | # foreword
17 |
18 | Mathematical symbols can mean different things depending on the author, context and the field of study (linear algebra, set theory, etc). This guide may not cover *all* uses of a symbol. In some cases, real-world references (blog posts, publications, etc) will be cited to demonstrate how a symbol might appear in the wild.
19 |
20 | For a more complete list, refer to [Wikipedia - List of Mathematical Symbols](https://en.wikipedia.org/wiki/List_of_mathematical_symbols).
21 |
22 | For simplicity, many of the code examples here operate on floating point values and are not numerically robust. For more details on why this may be a problem, see [Robust Arithmetic Notes](https://github.com/mikolalysenko/robust-arithmetic-notes) by Mikola Lysenko.
23 |
24 | # contents
25 |
26 | - [variable name conventions](#variable-name-conventions)
27 | - [equals `=` `≈` `≠` `:=`](#equals-symbols)
28 | - [square root and complex numbers `√` *`i`*](#square-root-and-complex-numbers)
29 | - [dot & cross `·` `×` `∘`](#dot--cross)
30 | - [scalar multiplication](#scalar-multiplication)
31 | - [vector multiplication](#vector-multiplication)
32 | - [dot product](#dot-product)
33 | - [cross product](#cross-product)
34 | - [sigma `Σ`](#sigma) - *summation*
35 | - [capital Pi `Π`](#capital-pi) - *products of sequences*
36 | - [pipes `||`](#pipes)
37 | - [absolute value](#absolute-value)
38 | - [Euclidean norm](#euclidean-norm)
39 | - [determinant](#determinant)
40 | - [hat **`â`**](#hat) - *unit vector*
41 | - ["element of" `∈` `∉`](#element)
42 | - [common number sets `ℝ` `ℤ` `ℚ` `ℕ`](#common-number-sets)
43 | - [function `ƒ`](#function)
44 | - [piecewise function](#piecewise-function)
45 | - [common functions](#common-functions)
46 | - [function notation `↦` `→`](#function-notation)
47 | - [prime `′`](#prime)
48 | - [floor & ceiling `⌊` `⌉`](#floor--ceiling)
49 | - [arrows](#arrows)
50 | - [material implication `⇒` `→`](#material-implication)
51 | - [equality `<` `≥` `≫`](#equality)
52 | - [conjunction & disjunction `∧` `∨`](#conjunction--disjunction)
53 | - [logical negation `¬` `~` `!`](#logical-negation)
54 | - [intervals](#intervals)
55 | - [more...](#more)
56 |
57 | ## variable name conventions
58 |
59 | There are a variety of naming conventions depending on the context and field of study, and they are not always consistent. However, in some of the literature you may find variable names to follow a pattern like so:
60 |
61 | - *s* - italic lowercase letters for scalars (e.g. a number)
62 | - **x** - bold lowercase letters for vectors (e.g. a 2D point)
63 | - **A** - bold uppercase letters for matrices (e.g. a 3D transformation)
64 | - *θ* - italic lowercase Greek letters for constants and special variables (e.g. [polar angle *θ*, *theta*](https://en.wikipedia.org/wiki/Spherical_coordinate_system))
65 |
66 | This will also be the format of this guide.
67 |
68 | ## equals symbols
69 |
70 | There are a number of symbols resembling the equals sign `=`. Here are a few common examples:
71 |
72 | - `=` is for equality (values are the same)
73 | - `≠` is for inequality (value are not the same)
74 | - `≈` is for approximately equal to (`π ≈ 3.14159`)
75 | - `:=` is for definition (A is defined as B)
76 |
77 | In JavaScript:
78 |
79 | ```js
80 | // equality
81 | 2 === 3
82 |
83 | // inequality
84 | 2 !== 3
85 |
86 | // approximately equal
87 | almostEqual(Math.PI, 3.14159, 1e-5)
88 |
89 | function almostEqual(a, b, epsilon) {
90 | return Math.abs(a - b) <= epsilon
91 | }
92 | ```
93 |
94 | You might see the `:=`, `=:` and `=` symbols being used for *definition*.[1]
95 |
96 | For example, the following defines *x* to be another name for 2*kj*.
97 |
98 | 
99 |
100 |
101 |
102 | In JavaScript, we might use `var` to *define* our variables and provide aliases:
103 |
104 | ```js
105 | var x = 2 * k * j
106 | ```
107 |
108 | However, this is mutable, and only takes a snapshot of the values at that time. Some languages have pre-processor `#define` statements, which are closer to a mathematical *define*.
109 |
110 | A more accurate *define* in JavaScript (ES6) might look a bit like this:
111 |
112 | ```js
113 | const f = (k, j) => 2 * k * j
114 | ```
115 |
116 | The following, on the other hand, represents equality:
117 |
118 | 
119 |
120 |
121 |
122 | The above equation might be interpreted in code as an [assertion](https://developer.mozilla.org/en-US/docs/Web/API/console/assert):
123 |
124 | ```js
125 | console.assert(x === (2 * k * j))
126 | ```
127 |
128 | ## square root and complex numbers
129 |
130 | A square root operation is of the form:
131 |
132 | 
133 |
134 |
135 |
136 | In programming we use a `sqrt` function, like so:
137 |
138 | ```js
139 | var x = 9;
140 | console.log(Math.sqrt(x));
141 | //=> 3
142 | ```
143 |
144 | Complex numbers are expressions of the form , where  is the real part and  is the imaginary part. The imaginary number  is defined as:
145 |
146 | .
147 |
148 |
149 | In JavaScript, there is no built-in functionality for complex numbers, but there are some libraries that support complex number arithmetic. For example, using [mathjs](https://www.npmjs.com/package/mathjs):
150 |
151 | ```js
152 | var math = require('mathjs')
153 |
154 | var a = math.complex(3, -1)
155 | //=> { re: 3, im: -1 }
156 |
157 | var b = math.sqrt(-1)
158 | //=> { re: 0, im: 1 }
159 |
160 | console.log(math.multiply(a, b).toString())
161 | //=> '1 + 3i'
162 | ```
163 |
164 | The library also supports evaluating a string expression, so the above could be re-written as:
165 |
166 | ```js
167 | console.log(math.eval('(3 - i) * i').toString())
168 | //=> '1 + 3i'
169 | ```
170 |
171 | Other implementations:
172 |
173 | - [immutable-complex](https://www.npmjs.com/package/immutable-complex)
174 | - [complex-js](https://www.npmjs.com/package/complex-js)
175 | - [Numeric-js](http://www.numericjs.com/)
176 |
177 | ## dot & cross
178 |
179 | The dot `·` and cross `×` symbols have different uses depending on context.
180 |
181 | They might seem obvious, but it's important to understand the subtle differences before we continue into other sections.
182 |
183 | #### scalar multiplication
184 |
185 | Both symbols can represent simple multiplication of scalars. The following are equivalent:
186 |
187 | 
188 |
189 |
190 |
191 | In programming languages we tend to use asterisk for multiplication:
192 |
193 | ```js
194 | var result = 5 * 4
195 | ```
196 |
197 | Often, the multiplication sign is only used to avoid ambiguity (e.g. between two numbers). Here, we can omit it entirely:
198 |
199 | 
200 |
201 |
202 |
203 | If these variables represent scalars, the code would be:
204 |
205 | ```js
206 | var result = 3 * k * j
207 | ```
208 |
209 | #### vector multiplication
210 |
211 | To denote multiplication of one vector with a scalar, or element-wise multiplication of a vector with another vector, we typically do not use the dot `·` or cross `×` symbols. These have different meanings in linear algebra, discussed shortly.
212 |
213 | Let's take our earlier example but apply it to vectors. For element-wise vector multiplication, you might see an open dot `∘` to represent the [Hadamard product](https://en.wikipedia.org/wiki/Hadamard_product_%28matrices%29).[2]
214 |
215 | 
216 |
217 |
218 |
219 | In other instances, the author might explicitly define a different notation, such as a circled dot `⊙` or a filled circle `●`.[3]
220 |
221 | Here is how it would look in code, using arrays `[x, y]` to represent the 2D vectors.
222 |
223 | ```js
224 | var s = 3
225 | var k = [ 1, 2 ]
226 | var j = [ 2, 3 ]
227 |
228 | var tmp = multiply(k, j)
229 | var result = multiplyScalar(tmp, s)
230 | //=> [ 6, 18 ]
231 | ```
232 |
233 | Our `multiply` and `multiplyScalar` functions look like this:
234 |
235 | ```js
236 | function multiply(a, b) {
237 | return [ a[0] * b[0], a[1] * b[1] ]
238 | }
239 |
240 | function multiplyScalar(a, scalar) {
241 | return [ a[0] * scalar, a[1] * scalar ]
242 | }
243 | ```
244 |
245 | Similarly, matrix multiplication typically does not use the dot `·` or cross symbol `×`. Matrix multiplication will be covered in a later section.
246 |
247 | #### dot product
248 |
249 | The dot symbol `·` can be used to denote the [*dot product*](https://en.wikipedia.org/wiki/Dot_product) of two vectors. Sometimes this is called the *scalar product* since it evaluates to a scalar.
250 |
251 | 
252 |
253 |
254 |
255 | It is a very common feature of linear algebra, and with a 3D vector it might look like this:
256 |
257 | ```js
258 | var k = [ 0, 1, 0 ]
259 | var j = [ 1, 0, 0 ]
260 |
261 | var d = dot(k, j)
262 | //=> 0
263 | ```
264 |
265 | The result `0` tells us our vectors are perpendicular. Here is a `dot` function for 3-component vectors:
266 |
267 | ```js
268 | function dot(a, b) {
269 | return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
270 | }
271 | ```
272 |
273 | #### cross product
274 |
275 | The cross symbol `×` can be used to denote the [*cross product*](https://en.wikipedia.org/wiki/Cross_product) of two vectors.
276 |
277 | 
278 |
279 |
280 |
281 | In code, it would look like this:
282 |
283 | ```js
284 | var k = [ 0, 1, 0 ]
285 | var j = [ 1, 0, 0 ]
286 |
287 | var result = cross(k, j)
288 | //=> [ 0, 0, -1 ]
289 | ```
290 |
291 | Here, we get `[ 0, 0, -1 ]`, which is perpendicular to both **k** and **j**.
292 |
293 | Our `cross` function:
294 |
295 | ```js
296 | function cross(a, b) {
297 | var ax = a[0], ay = a[1], az = a[2],
298 | bx = b[0], by = b[1], bz = b[2]
299 |
300 | var rx = ay * bz - az * by
301 | var ry = az * bx - ax * bz
302 | var rz = ax * by - ay * bx
303 | return [ rx, ry, rz ]
304 | }
305 | ```
306 |
307 | For other implementations of vector multiplication, cross product, and dot product:
308 |
309 | - [gl-vec3](https://github.com/stackgl/gl-vec3)
310 | - [gl-vec2](https://github.com/stackgl/gl-vec2)
311 | - [vectors](https://github.com/hughsk/vectors) - includes n-dimensional
312 |
313 | ## sigma
314 |
315 | The big Greek `Σ` (Sigma) is for [Summation](https://en.wikipedia.org/wiki/Summation). In other words: summing up some numbers.
316 |
317 | 
318 |
319 |
320 |
321 | Here, `i=1` says to start at `1` and end at the number above the Sigma, `100`. These are the lower and upper bounds, respectively. The *i* to the right of the "E" tells us what we are summing. In code:
322 |
323 | ```js
324 | var sum = 0
325 | for (var i = 1; i <= 100; i++) {
326 | sum += i
327 | }
328 | ```
329 |
330 | The result of `sum` is `5050`.
331 |
332 | **Tip:** With whole numbers, this particular pattern can be optimized to the following:
333 |
334 | ```js
335 | var n = 100 // upper bound
336 | var sum = (n * (n + 1)) / 2
337 | ```
338 |
339 | Here is another example where the *i*, or the "what to sum," is different:
340 |
341 | 
342 |
343 |
344 |
345 | In code:
346 |
347 | ```js
348 | var sum = 0
349 | for (var i = 1; i <= 100; i++) {
350 | sum += (2 * i + 1)
351 | }
352 | ```
353 |
354 | The result of `sum` is `10200`.
355 |
356 | The notation can be nested, which is much like nesting a `for` loop. You should evaluate the right-most sigma first, unless the author has enclosed them in parentheses to alter the order. However, in the following case, since we are dealing with finite sums, the order does not matter.
357 |
358 | 
359 |
360 |
361 |
362 | In code:
363 |
364 | ```js
365 | var sum = 0
366 | for (var i = 1; i <= 2; i++) {
367 | for (var j = 4; j <= 6; j++) {
368 | sum += (3 * i * j)
369 | }
370 | }
371 | ```
372 |
373 | Here, `sum` will be `135`.
374 |
375 | ## capital Pi
376 |
377 | The capital Pi or "Big Pi" is very similar to [Sigma](#sigma), except we are using multiplication to find the product of a sequence of values.
378 |
379 | Take the following:
380 |
381 | 
382 |
383 |
384 |
385 | In code, it might look like this:
386 |
387 | ```js
388 | var value = 1
389 | for (var i = 1; i <= 6; i++) {
390 | value *= i
391 | }
392 | ```
393 |
394 | Where `value` will evaluate to `720`.
395 |
396 | ## pipes
397 |
398 | Pipe symbols, known as *bars*, can mean different things depending on the context. Below are three common uses: [absolute value](#absolute-value), [Euclidean norm](#euclidean-norm), and [determinant](#determinant).
399 |
400 | These three features all describe the *length* of an object.
401 |
402 | #### absolute value
403 |
404 | 
405 |
406 |
407 |
408 | For a number *x*, `|x|` means the absolute value of *x*. In code:
409 |
410 | ```js
411 | var x = -5
412 | var result = Math.abs(x)
413 | // => 5
414 | ```
415 |
416 | #### Euclidean norm
417 |
418 | 
419 |
420 |
421 |
422 | For a vector **v**, `‖v‖` is the [Euclidean norm](https://en.wikipedia.org/wiki/Norm_%28mathematics%29#Euclidean_norm) of **v**. It is also referred to as the "magnitude" or "length" of a vector.
423 |
424 | Often this is represented by double-bars to avoid ambiguity with the *absolute value* notation, but sometimes you may see it with single bars:
425 |
426 | 
427 |
428 |
429 |
430 | Here is an example using an array `[x, y, z]` to represent a 3D vector.
431 |
432 | ```js
433 | var v = [ 0, 4, -3 ]
434 | length(v)
435 | //=> 5
436 | ```
437 |
438 | The `length` function:
439 |
440 | ```js
441 | function length (vec) {
442 | var x = vec[0]
443 | var y = vec[1]
444 | var z = vec[2]
445 | return Math.sqrt(x * x + y * y + z * z)
446 | }
447 | ```
448 |
449 | Other implementations:
450 |
451 | - [magnitude](https://github.com/mattdesl/magnitude/blob/864ff5a7eb763d34bf154ac5f5332d7601192b70/index.js) - n-dimensional
452 | - [gl-vec2/length](https://github.com/stackgl/gl-vec2/blob/21f460a371540258521fd2f720d80f14e87bd400/length.js) - 2D vector
453 | - [gl-vec3/length](https://github.com/stackgl/gl-vec3/blob/507480fa57ba7c5fb70679cf531175a52c48cf53/length.js) - 3D vector
454 |
455 | #### determinant
456 |
457 | 
458 |
459 |
460 |
461 | For a matrix **A**, `|A|` means the [determinant](https://en.wikipedia.org/wiki/Determinant) of matrix **A**.
462 |
463 | Here is an example computing the determinant of a 2x2 matrix, represented by a flat array in column-major format.
464 |
465 | ```js
466 | var determinant = require('gl-mat2/determinant')
467 |
468 | var matrix = [ 1, 0, 0, 1 ]
469 | var det = determinant(matrix)
470 | //=> 1
471 | ```
472 |
473 | Implementations:
474 |
475 | - [gl-mat4/determinant](https://github.com/stackgl/gl-mat4/blob/c2e2de728fe7eba592f74cd02266100cc21ec89a/determinant.js) - also see [gl-mat3](https://github.com/stackgl/gl-mat3) and [gl-mat2](https://github.com/stackgl/gl-mat2)
476 | - [ndarray-determinant](https://www.npmjs.com/package/ndarray-determinant)
477 | - [glsl-determinant](https://www.npmjs.com/package/glsl-determinant)
478 | - [robust-determinant](https://www.npmjs.com/package/robust-determinant)
479 | - [robust-determinant-2](https://www.npmjs.com/package/robust-determinant-2) and [robust-determinant-3](https://www.npmjs.com/package/robust-determinant-3), specifically for 2x2 and 3x3 matrices, respectively
480 |
481 | ## hat
482 |
483 | In geometry, the "hat" symbol above a character is used to represent a [unit vector](https://en.wikipedia.org/wiki/Unit_vector). For example, here is the unit vector of **a**:
484 |
485 | 
486 |
487 |
488 |
489 | In Cartesian space, a unit vector is typically length 1. That means each part of the vector will be in the range of -1.0 to 1.0. Here we *normalize* a 3D vector into a unit vector:
490 |
491 | ```js
492 | var a = [ 0, 4, -3 ]
493 | normalize(a)
494 | //=> [ 0, 0.8, -0.6 ]
495 | ```
496 |
497 | Here is the `normalize` function, operating on 3D vectors:
498 |
499 | ```js
500 | function normalize(vec) {
501 | var x = vec[0]
502 | var y = vec[1]
503 | var z = vec[2]
504 | var squaredLength = x * x + y * y + z * z
505 |
506 | if (squaredLength > 0) {
507 | var length = Math.sqrt(squaredLength)
508 | vec[0] = x / length
509 | vec[1] = y / length
510 | vec[2] = z / length
511 | }
512 | return vec
513 | }
514 | ```
515 |
516 | Other implementations:
517 |
518 | - [gl-vec3/normalize](https://github.com/stackgl/gl-vec3/blob/507480fa57ba7c5fb70679cf531175a52c48cf53/normalize.js) and [gl-vec2/normalize](https://github.com/stackgl/gl-vec2/blob/21f460a371540258521fd2f720d80f14e87bd400/normalize.js)
519 | - [vectors/normalize-nd](https://github.com/hughsk/vectors/blob/master/normalize-nd.js) (n-dimensional)
520 |
521 | ## element
522 |
523 | In set theory, the "element of" symbol `∈` and `∋` can be used to describe whether something is an element of a *set*. For example:
524 |
525 | 
526 |
527 |
528 |
529 | Here we have a set of numbers *A* `{ 3, 9, 14 }` and we are saying `3` is an "element of" that set.
530 |
531 | A simple implementation in ES5 might look like this:
532 |
533 | ```js
534 | var A = [ 3, 9, 14 ]
535 |
536 | A.indexOf(3) >= 0
537 | //=> true
538 | ```
539 |
540 | However, it would be more accurate to use a `Set` which only holds unique values. This is a feature of ES6.
541 |
542 | ```js
543 | var A = new Set([ 3, 9, 14 ])
544 |
545 | A.has(3)
546 | //=> true
547 | ```
548 |
549 | The backwards `∋` is the same, but the order changes:
550 |
551 | 
552 |
553 |
554 |
555 | You can also use the "not an element of" symbols `∉` and `∌` like so:
556 |
557 | 
558 |
559 |
560 |
561 | ## common number sets
562 |
563 | You may see some some large [Blackboard](https://en.wikipedia.org/wiki/Blackboard_bold) letters among equations. Often, these are used to describe sets.
564 |
565 | For example, we might describe *k* to be an [element of](#element) the set `ℝ`.
566 |
567 | 
568 |
569 |
570 |
571 | Listed below are a few common sets and their symbols.
572 |
573 | #### `ℝ` real numbers
574 |
575 | The large `ℝ` describes the set of *real numbers*. These include integers, as well as rational and irrational numbers.
576 |
577 | JavaScript treats floats and integers as the same type, so the following would be a simple test of our *k* ∈ ℝ example:
578 |
579 | ```js
580 | function isReal (k) {
581 | return typeof k === 'number' && isFinite(k);
582 | }
583 | ```
584 |
585 | *Note:* Real numbers are also *finite*, as in, *not infinite.*
586 |
587 | #### `ℚ` rational numbers
588 |
589 | Rational numbers are real numbers that can be expressed as a fraction, or *ratio* (like `⅗`). Rational numbers cannot have zero as a denominator.
590 |
591 | This also means that all integers are rational numbers, since the denominator can be expressed as 1.
592 |
593 | An irrational number, on the other hand, is one that cannot be expressed as a ratio, like π (PI).
594 |
595 | #### `ℤ` integers
596 |
597 | An integer, i.e. a real number that has no fractional part. These can be positive or negative.
598 |
599 | A simple test in JavaScript might look like this:
600 |
601 | ```js
602 | function isInteger (n) {
603 | return typeof n === 'number' && n % 1 === 0
604 | }
605 | ```
606 |
607 | #### `ℕ` natural numbers
608 |
609 | A natural number, a positive and non-negative integer. Depending on the context and field of study, the set may or may not include zero, so it could look like either of these:
610 |
611 | ```js
612 | { 0, 1, 2, 3, ... }
613 | { 1, 2, 3, 4, ... }
614 | ```
615 |
616 | The former is more common in computer science, for example:
617 |
618 | ```js
619 | function isNaturalNumber (n) {
620 | return isInteger(n) && n >= 0
621 | }
622 | ```
623 |
624 | #### `ℂ` complex numbers
625 |
626 | A complex number is a combination of a real and imaginary number, viewed as a co-ordinate in the 2D plane. For more info, see [A Visual, Intuitive Guide to Imaginary Numbers](http://betterexplained.com/articles/a-visual-intuitive-guide-to-imaginary-numbers/).
627 |
628 | ## function
629 |
630 | [Functions](https://en.wikipedia.org/wiki/Function_%28mathematics%29) are fundamental features of mathematics, and the concept is fairly easy to translate into code.
631 |
632 | A function relates an input to an output value. For example, the following is a function:
633 |
634 | 
635 |
636 |
637 |
638 | We can give this function a *name*. Commonly, we use `ƒ` to describe a function, but it could be named `A(x)` or anything else.
639 |
640 | 
641 |
642 |
643 |
644 | In code, we might name it `square` and write it like this:
645 |
646 | ```js
647 | function square (x) {
648 | return Math.pow(x, 2)
649 | }
650 | ```
651 |
652 | Sometimes a function is not named, and instead the output is written.
653 |
654 | 
655 |
656 |
657 |
658 | In the above example, *x* is the input, the relationship is *squaring*, and *y* is the output.
659 |
660 | Functions can also have multiple parameters, like in a programming language. These are known as *arguments* in mathematics, and the number of arguments a function takes is known as the *arity* of the function.
661 |
662 | 
663 |
664 |
665 |
666 | In code:
667 |
668 | ```js
669 | function length (x, y) {
670 | return Math.sqrt(x * x + y * y)
671 | }
672 | ```
673 |
674 | ### piecewise function
675 |
676 | Some functions will use different relationships depending on the input value, *x*.
677 |
678 | The following function *ƒ* chooses between two "sub functions" depending on the input value.
679 |
680 | 
681 |
682 |
687 |
688 | This is very similar to `if` / `else` in code. The right-side conditions are often written as **"for x < 0"** or **"if x = 0"**. If the condition is true, the function to the left is used.
689 |
690 | In piecewise functions, **"otherwise"** and **"elsewhere"** are analogous to the `else` statement in code.
691 |
692 | ```js
693 | function f (x) {
694 | if (x >= 1) {
695 | return (Math.pow(x, 2) - x) / x
696 | } else {
697 | return 0
698 | }
699 | }
700 | ```
701 |
702 | ### common functions
703 |
704 | There are some function names that are ubiquitous in mathematics. For a programmer, these might be analogous to functions "built-in" to the language (like `parseInt` in JavaScript).
705 |
706 | One such example is the *sgn* function. This is the *signum* or *sign* function. Let's use [piecewise function](#piecewise-function) notation to describe it:
707 |
708 | 
709 |
710 |
716 |
717 | In code, it might look like this:
718 |
719 | ```js
720 | function sgn (x) {
721 | if (x < 0) return -1
722 | if (x > 0) return 1
723 | return 0
724 | }
725 | ```
726 |
727 | See [signum](https://github.com/scijs/signum) for this function as a module.
728 |
729 | Other examples of such functions: *sin*, *cos*, *tan*.
730 |
731 | ### function notation
732 |
733 | In some literature, functions may be defined with more explicit notation. For example, let's go back to the `square` function we mentioned earlier:
734 |
735 | 
736 |
737 |
738 |
739 | It might also be written in the following form:
740 |
741 | 
742 |
743 |
744 |
745 | The arrow here with a tail typically means "maps to," as in *x maps to x2*.
746 |
747 | Sometimes, when it isn't obvious, the notation will also describe the *domain* and *codomain* of the function. A more formal definition of *ƒ* might be written as:
748 |
749 | 
750 |
751 |
756 |
757 | A function's *domain* and *codomain* is a bit like its *input* and *output* types, respectively. Here's another example, using our earlier *sgn* function, which outputs an integer:
758 |
759 | 
760 |
761 |
762 |
763 | The arrow here (without a tail) is used to map one *set* to another.
764 |
765 | In JavaScript and other dynamically typed languages, you might use documentation and/or runtime checks to explain and validate a function's input/output. Example:
766 |
767 | ```js
768 | /**
769 | * Squares a number.
770 | * @param {Number} a real number
771 | * @return {Number} a real number
772 | */
773 | function square (a) {
774 | if (typeof a !== 'number') {
775 | throw new TypeError('expected a number')
776 | }
777 | return Math.pow(a, 2)
778 | }
779 | ```
780 |
781 | Some tools like [flowtype](http://flowtype.org/) attempt to bring static typing into JavaScript.
782 |
783 | Other languages, like Java, allow for true method overloading based on the static types of a function's input/output. This is closer to mathematics: two functions are not the same if they use a different *domain*.
784 |
785 | ## prime
786 |
787 | The prime symbol (`′`) is often used in variable names to describe things which are similar, without giving it a different name altogether. It can describe the "next value" after some transformation.
788 |
789 | For example, if we take a 2D point *(x, y)* and rotate it, you might name the result *(x′, y′)*. Or, the *transpose* of matrix **M** might be named **M′**.
790 |
791 | In code, we typically just assign the variable a more descriptive name, like `transformedPosition`.
792 |
793 | For a mathematical [function](#function), the prime symbol often describes the *derivative* of that function. Derivatives will be explained in a future section. Let's take our earlier function:
794 |
795 | 
796 |
797 |
798 |
799 | Its derivative could be written with a prime `′` symbol:
800 |
801 | 
802 |
803 |
804 |
805 | In code:
806 |
807 | ```js
808 | function f (x) {
809 | return Math.pow(x, 2)
810 | }
811 |
812 | function fPrime (x) {
813 | return 2 * x
814 | }
815 | ```
816 |
817 | Multiple prime symbols can be used to describe the second derivative *ƒ′′* and third derivative *ƒ′′′*. After this, authors typically express higher orders with roman numerals *ƒ*IV or superscript numbers *ƒ*(n).
818 |
819 | ## floor & ceiling
820 |
821 | The special brackets `⌊x⌋` and `⌈x⌉` represent the *floor* and *ceil* functions, respectively.
822 |
823 | 
824 |
825 |
826 |
827 | 
828 |
829 |
830 |
831 | In code:
832 |
833 | ```js
834 | Math.floor(x)
835 | Math.ceil(x)
836 | ```
837 |
838 | When the two symbols are mixed `⌊x⌉`, it typically represents a function that rounds to the nearest integer:
839 |
840 | 
841 |
842 |
843 |
844 | In code:
845 |
846 | ```js
847 | Math.round(x)
848 | ```
849 |
850 | ## arrows
851 |
852 | Arrows are often used in [function notation](#function-notation). Here are a few other areas you might see them.
853 |
854 | #### material implication
855 |
856 | Arrows like `⇒` and `→` are sometimes used in logic for *material implication.* That is, if A is true, then B is also true.
857 |
858 | 
859 |
860 |
861 |
862 | Interpreting this as code might look like this:
863 |
864 | ```js
865 | if (A === true) {
866 | console.assert(B === true)
867 | }
868 | ```
869 |
870 | The arrows can go in either direction `⇐` `⇒`, or both `⇔`. When *A ⇒ B* and *B ⇒ A*, they are said to be equivalent:
871 |
872 | 
873 |
874 |
875 |
876 | #### equality
877 |
878 | In math, the `<` `>` `≤` and `≥` are typically used in the same way we use them in code: *less than*, *greater than*, *less than or equal to* and *greater than or equal to*, respectively.
879 |
880 | ```js
881 | 50 > 2 === true
882 | 2 < 10 === true
883 | 3 <= 4 === true
884 | 4 >= 4 === true
885 | ```
886 |
887 | On rare occasions you might see a slash through these symbols, to describe *not*. As in, *k* is "not greater than" *j*.
888 |
889 | 
890 |
891 |
892 |
893 | The `≪` and `≫` are sometimes used to represent *significant* inequality. That is, *k* is an [order of magnitude](https://en.wikipedia.org/wiki/Order_of_magnitude) larger than *j*.
894 |
895 | 
896 |
897 |
898 |
899 | In mathematics, *order of magnitude* is rather specific; it is not just a "really big difference." A simple example of the above:
900 |
901 | ```js
902 | orderOfMagnitude(k) > orderOfMagnitude(j)
903 | ```
904 |
905 | And below is our `orderOfMagnitude` function, using [Math.trunc](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc) (ES6).
906 |
907 | ```js
908 | function log10(n) {
909 | // logarithm in base 10
910 | return Math.log(n) / Math.LN10
911 | }
912 |
913 | function orderOfMagnitude (n) {
914 | return Math.trunc(log10(n))
915 | }
916 | ```
917 |
918 | *Note:* This is not numerically robust.
919 |
920 | See [math-trunc](https://www.npmjs.com/package/math-trunc) for a ponyfill in ES5.
921 |
922 | #### conjunction & disjunction
923 |
924 | Another use of arrows in logic is conjunction `∧` and disjunction `∨`. They are analogous to a programmer's `AND` and `OR` operators, respectively.
925 |
926 | The following shows conjunction `∧`, the logical `AND`.
927 |
928 | 
929 |
930 |
931 |
932 | In JavaScript, we use `&&`. Assuming *k* is a natural number, the logic implies that *k* is 3:
933 |
934 | ```js
935 | if (k > 2 && k < 4) {
936 | console.assert(k === 3)
937 | }
938 | ```
939 |
940 | Since both sides are equivalent `⇔`, it also implies the following:
941 |
942 | ```js
943 | if (k === 3) {
944 | console.assert(k > 2 && k < 4)
945 | }
946 | ```
947 |
948 | The down arrow `∨` is logical disjunction, like the OR operator.
949 |
950 | 
951 |
952 |
953 |
954 | In code:
955 |
956 | ```js
957 | A || B
958 | ```
959 |
960 | ## logical negation
961 |
962 | Occasionally, the `¬`, `~` and `!` symbols are used to represent logical `NOT`. For example, *¬A* is only true if A is false.
963 |
964 | Here is a simple example using the *not* symbol:
965 |
966 | 
967 |
968 |
969 |
970 | An example of how we might interpret this in code:
971 |
972 | ```js
973 | if (x !== y) {
974 | console.assert(!(x === y))
975 | }
976 | ```
977 |
978 | *Note:* The tilde `~` has many different meanings depending on context. For example, *row equivalence* (matrix theory) or *same order of magnitude* (discussed in [equality](#equality)).
979 |
980 | ## intervals
981 |
982 | Sometimes a function deals with real numbers restricted to some range of values, such a constraint can be represented using an *interval*
983 |
984 | For example we can represent the numbers between zero and one including/not including zero and/or one as:
985 |
986 | - Not including zero or one: 
987 |
988 |
989 |
990 | - Including zero or but not one: 
991 |
992 |
993 |
994 | - Not including zero but including one: 
995 |
996 |
997 |
998 | - Including zero and one: 
999 |
1000 |
1001 |
1002 | For example we to indicate that a point `x` is in the unit cube in 3D we say:
1003 |
1004 | 
1005 |
1006 |
1007 |
1008 | In code we can represent an interval using a two element 1d array:
1009 |
1010 | ```js
1011 | var nextafter = require('nextafter')
1012 |
1013 | var a = [nextafter(0, Infinity), nextafter(1, -Infinity)] // open interval
1014 | var b = [nextafter(0, Infinity), 1] // interval closed on the left
1015 | var c = [0, nextafter(1, -Infinity)] // interval closed on the right
1016 | var d = [0, 1] // closed interval
1017 | ```
1018 |
1019 | Intervals are used in conjunction with set operations:
1020 |
1021 | - *intersection* e.g. 
1022 |
1023 |
1024 |
1025 | - *union* e.g. 
1026 |
1027 |
1028 |
1029 | - *difference* e.g.  and 
1030 |
1031 |
1032 |
1033 |
1034 | In code:
1035 |
1036 | ```js
1037 | var Interval = require('interval-arithmetic')
1038 | var nextafter = require('nextafter')
1039 |
1040 | var a = Interval(3, nextafter(5, -Infinity))
1041 | var b = Interval(4, 6)
1042 |
1043 | Interval.intersection(a, b)
1044 | // {lo: 4, hi: 4.999999999999999}
1045 |
1046 | Interval.union(a, b)
1047 | // {lo: 3, hi: 6}
1048 |
1049 | Interval.difference(a, b)
1050 | // {lo: 3, hi: 3.9999999999999996}
1051 |
1052 | Interval.difference(b, a)
1053 | // {lo: 5, hi: 6}
1054 | ```
1055 |
1056 | See:
1057 |
1058 | - [next-after](https://github.com/scijs/nextafter)
1059 | - [interval-arithmetic](https://github.com/maurizzzio/interval-arithmetic)
1060 |
1061 | ## more...
1062 |
1063 | Like this guide? Suggest some [more features](https://github.com/Jam3/math-as-code/issues/1) or send us a Pull Request!
1064 |
1065 | ## Contributing
1066 |
1067 | For details on how to contribute, see [CONTRIBUTING.md](./CONTRIBUTING.md).
1068 |
1069 | ## License
1070 |
1071 | MIT, see [LICENSE.md](http://github.com/Jam3/math-as-code/blob/master/LICENSE.md) for details.
1072 |
1073 | [1]: http://mimosa-pudica.net/improved-oren-nayar.html#images
1074 | [2]: http://buzzard.ups.edu/courses/2007spring/projects/million-paper.pdf
1075 | [3]: https://www.math.washington.edu/~morrow/464_12/fft.pdf
1076 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "math-as-code",
3 | "version": "1.0.0",
4 | "description": "a reference for mathematical notation in code form",
5 | "main": "index.js",
6 | "license": "MIT",
7 | "author": {
8 | "name": "Matt DesLauriers",
9 | "email": "dave.des@gmail.com",
10 | "url": "https://github.com/mattdesl"
11 | },
12 | "dependencies": {
13 | "math-trunc": "^1.0.0"
14 | },
15 | "devDependencies": {},
16 | "scripts": {
17 | "test": "node test.js"
18 | },
19 | "keywords": [
20 | "learning",
21 | "math",
22 | "mathematical",
23 | "notation",
24 | "symbol",
25 | "symbols",
26 | "cheat",
27 | "sheet",
28 | "cheatsheet",
29 | "help",
30 | "guide",
31 | "walkthrough",
32 | "tutorial",
33 | "mathematics",
34 | "language"
35 | ],
36 | "repository": {
37 | "type": "git",
38 | "url": "git://github.com/Jam3/math-as-code.git"
39 | },
40 | "homepage": "https://github.com/Jam3/math-as-code",
41 | "bugs": {
42 | "url": "https://github.com/Jam3/math-as-code/issues"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------