3.1 Math and Numbers
# JavaScript Numbers
In JavaScript, a number value can be an integer or a float value. This means that it can include decimal values. A Number
is one of the JavaScript primitive datatypes, which means that it just a value.
However, just like Strings, there is also a Number Object
which will be created behind the scenes when needed. This gives us a few number methods that we can use.
The Number Object
has some methods that you would call directly from the number primitive variable, just like we did with the String methods. It also has a few methods that get called from the Number
object directly and they want to be passed some other variable because they want to examine that other variable to see if it is numeric or if it could be converted to into a number primitive.
let num = 3.14;
//these first two methods are called on the number object created for the variable `num`.
num.toFixed(2); //round off the number to a specific number of decimal points
//Method returns a STRING
num.toString(); //returns what you see in the variable str
let strFloat = '3.14'; //A string that contains a numerical float values
let strInteger = '7'; //a string that contains an integer value
//these other methods use the Number Object container, not the variable
//they ask for a string
Number.parseInt(strFloat); //convert the number to an integer.
//Method returns an integer
Number.parseFloat(strFloat); //returns the float version of
Number.isNaN(strFloat); //check if the number in the variable is Not A Number (NaN)
//returns a true or false (Boolean)
Number.isInteger(strInteger); //checks if the value in the variable is an integer.
//returns true or false. False if the number has decimals eg: 3.14
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Number Bases
Every value that is stored in a traditional, non-quantum, computer is stored as a series of ones and zeros, known as bits. Commonly these are grouped together 8 bits at a time. 8 bits is known as a byte.
Network speeds are measured in how many bits that they can transmit or receive per second. A 1Gb connection means that you can receive 1 Giga-bits (1,000,000,000) per second. Note the lowercase b
in Gb
.
Device storage is measured in bytes. If your laptop has a 512GB Solid State Drive then it can hold 512 GigaBytes of data. Note the capital B
in GB
.
When you are looking at the data stored or transmitted as a string of ones and zeros then you are actually looking at numbers that are written in base-2. Base-2 means that there are only 2 possible digits allowed to be used when writing a number. Base-10 is what we normally use in our daily life. We are familiar with the digits 0 - 9. Ten different digits meaning base-10.
Another common base is hexadecimal, also known as base-16. This is one of the ways you can write your colours in CSS. #FF0014
is a valid CSS colour written in hex. The red value is FF
which in base-10 is 255
. The green value is 00
or 0
which is the same in any base. The blue value is 14
in hex or 20
in base-10.
Numbers can be written in any base. It doesn't change the value, it is just a different way of representing it.
So, why do we use FF as the biggest value for a colour channel?
- Decimal (base-10) 255
- Hexadecimal (base-16) FF
- Binaray (base-2) 1111 1111 - the way it is stored/represented in your computer
The number 255
or FF
is the biggest number you can hold in a single byte.
Ever heard people talk about 24 bit or 32 bit images? how about 32 or 64 bit processors? They are talking about the number of bits that need to be used to represent the each colour pixel in the image or the number of bits that get used at a time by the CPU.
A jpg
is a 24-bit image. It needs 8 bits for red, 8 bits for green and 8 bits for blue for each pixel. It has no transparency. A png
can be a 32-bit image. The extra 8 bits per pixel are to represent the level of transparency for that pixel, on top of the red, green, and blue.
What about counting in binary or hex?
The way counting works in any base is actually the same. In base-10 you have 10 possible digits. Once you have used all the digits, add another column set to 1 and then go through the 10 possible digits again in the original column. Repeat until you have been through every combination and then add another column.
In base-16 (hexadecimal) we need 16 different digits. So, where do we get the last 6 after 9? We use the letters A-F.
In base-36 we use 0-9 plus the full alphabet.
In base-64 we use 0-9
, plus a-z
, plus A-Z
, which gives use 62 digits and then +
and /
as the last two digits. =
is also used as a special character in base-64. Base-64 is a special thing though used for encoding strings and data for transmission and storage. The counting through the digits works the same but it's purpose goes beyond just representing numeric values.
Here are some examples with decimal, binary, and hex:
0 0 0
1 1 1
2 10 2
3 11 3
4 100 4
5 101 5
6 110 6
7 111 7
8 1000 8
9 1001 9
10 1010 A
11 1011 B
12 1100 C
13 1101 D
14 1110 E
15 1111 F
16 10000 10
...
97 1100001 61
98 1100010 62
99 1100011 63
100 1100100 64
101 1100101 65
102 1100110 66
...
254 11111110 FE
255 11111111 FF
256 100000000 100
...
998 1111100110 3E6
999 1111100111 3E7
1000 1111101000 3E8
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
To write your numeric values specifically in decimal we just write the number. If we want to write a number in base-8, base-2, or base-16 then there is special notation we can use.
All four variables in the following snippet have the same value, 20
, just written with different bases.
//default base is always 10
let twenty = 20;
//write a hex value by putting `0x` first
let twentyHex = 0x14;
//write a binary value by putting `0b` first
let twentyBinary = 0b10100;
//write an octal value by putting `0o` first
let tenOctal = 0o24;
2
3
4
5
6
7
8
9
10
11
# Math Operations
All the basic mathematical operations can be done in JavaScript.
let answer = 1 + 2; //addition
let answer = 2 - 1; //subtraction
let answer = 2 * 2; //multiplication
let answer = 4 / 2; //division
let answer = 3 ** 2; //exponents 3 to the power of 2
let answer = 9 % 4; // modulo 9 divided by 4 and then return the remainder of 1
2
3
4
5
6
# Incrementing and Decrementing
A frequent operation in programming is to repeatedly add or subtract one or the same value from a number.
let i = 7;
//add one to i
i = i + 1;
//short hand syntax to increment i
i += 1;
//or we can use the increment operator to add one
i++;
//subtract one from i
i = i - 1;
i -= 1;
i--; //decrement operator
2
3
4
5
6
7
8
9
10
11
12
13
All three versions in the above snippet are doing the same thing - they are adding or subtracting one from the variable i
.
If the value that you want to add or subtract from your variable is something other than one, then you can use either of the first two approaches.
let num = 0;
let increment = 5;
num = num + increment;
num += increment;
num = num - increment;
num -= increment;
2
3
4
5
6
7
8
The ++
and --
operators will always add or subtract one.
# The Math Object
JavaScript has a Math object which can carry out most common mathematical operations. If you need to round numbers up or down, complete Trigonometric calculations, determine which is the largest or smallest number, create a random number, determine if a number is positive or negative, or access the value of Pi
. All of these things can be accomplished with the Mathematical methods.
These methods all begin with the Math
object name.
Math.round(num); //returns the next highest or lowest integer depending on its decimal value.
Math.floor(num); //always rounds down to the next lowest integer
Math.ceil(num); //always rounds up to the next highest integer
Math.random(); //returns a random value between 0 and 1.
Math.max(list, of, numbers); //returns the largest number from the list
Math.min(list, of, numbers); //returns the smallest number from the list
Math.abs(num); //returns the absolute value of the number
Math.sign(num); //returns 1, -1, 0, -0, NaN to tell you if the number is positive or negative
Math.sin(radians); //returns the sine value for the provided radian value
Math.cos(radians); //returns the value of Cosine for the provided radian value
Math.tan(radians); //returns the value of Tangent for the provided radian value
Math.PI; //Use this as if it were a variable holding the value of Pi
2
3
4
5
6
7
8
9
10
11
12
And there are many more Numeric and Mathematical methods available. I encourage you to read through the list on the MDN site.
# NaN
Not A Number (NaN) is an Object in JavaScript that represents a value that is "Not A Number". You only get this value when you are trying to run a Number or Math that requires a numeric value.
There is also a global method isNaN()
, which is specifically designed to check if the value in a variable is a numeric one. Just pass a value or variable to the method and it will run the test and return a boolean.
It returns true
if the variable value is NOT numeric and false
if the value IS a numeric one.
let a = 'I am a string';
let b = false;
let c = 123;
let d = 123.45;
let e = '42';
isNaN(a); //true
isNaN(b); //false - surprisingly a Boolean is treated like 0 or 1 for false and true. A single bit.
isNaN(c); //false
isNaN(d); //false
isNaN(e); //false
2
3
4
5
6
7
8
9
10
11
# BigInt
As mentioned before, BitInt
is one of the primitive types which means that it is just a value. It is used specifically when you need to store a really big number that exceeds the Number.MAX_SAFE_INTEGER
to Number.MIN_SAFE_INTEGER
range.
This is not something that you are likely to encounter during this program.
To write a BigInt in your code just append a lowercase n
at the end of the number or use the BigInt()
constructor method.
//numbers over 9007199254740992 is the intended use
let big = 9007199254740999n;
//but you can store smaller numbers as the BigInt type
let otherbig = 1000n;
//you can use the BigInt construtor to create one too.
const huge = BigInt(9007199254740991);
2
3
4
5
6
Important notes about Big Int
All the basic Math operators are supported in BigInt
Fractional amounts will be removed from BigInt values
BitInt and Integers will match with ==
but not with ===
You can convert a BigInt back to an Integer Number with BigInt.asIntN()
BigInt MDN reference page (opens new window)
# Binary and Bitwise
Binary numbers are simply the representation of any number using base-2. When you see something written in binary it will be all ones and zeros, like this: 01100101 01100001 01110011 01110100 01100101 01110010 00100000 01100101 01100111 01100111
.
If you want to write a number in Binary in JavaScript just start the number with a zero then a lowercase b.
let binaryTen = 0b00001010;
//this is the number 10 in binary
2
The Bitwise operators allow us to use JavaScript and work with numbers at the binary level.
# The Bitwise AND operator
& - binary AND operator
The binary & operator is used to AND two numbers at the binary level
11001010
& 00001111 //the result of this is 00001010
2
For each bit we compare the values in each column and if both are a 1 then the result in that column is 1.
The bitwise OR
operator is |
the pipe character. It will compare two binary values and if either number in the column is a 1 then the result is a 1.
The bitwise NOT
operator is ~
and it will flip the bits in a number. All the zeros become ones and all the ones become zeros.
The bitwise XOR
operator is ^
. It will compare two binary values and return a one in each column where either bit is a one. If both bits are a one or if both bits are a zero then it returns a zero.
# The Bitwise Shift Operators
Sometimes we want to trim off the last few digits of a binary number or we want to add some more digits. The shift operators let us do that. The best example of this is when we want to extract the red, green, and blue parts of a colour value.
Hex colours are made up of three values 00-FF
, 00-FF
, and 00-FF
. Each one is a number between 0 and 255.
In binary, 255 is 11111111
. That is 8 ones. So, for each colour there are 8 bits. The colour white is (255, 255, 255) or #FFFFFF
.
In binary white would be 11111111 11111111 11111111
. That is why Jpegs are called 24 bit images. Each pixel is a colour made up of 24 bits. Black would be represented by 24 zeroes - 00000000 00000000 00000000
.
If you write 24 ones as a decimal number it is 2 to the power of 24 or 16,777,216.
A random colour would be a value between 0 and 16,777,216.
So, if we had the random number 1,654,344, in binary that would be 00011001 00111110 01001000
. The first 8 bits represent the red colour, the middle 8 bits are the green value, and the last 8 bits are the blue value.
If you want to extract those three parts of the one colour, we will use the shift operator.
For the red colour, we will shift the bits 16 places to the right. Basically, we are stripping off the rightmost 16 bits. Leaving us only the first 8 bits 00011001
. In decimal, that would be - 25.
For the blue colour, we will use the AND operator. We AND the whole number with 255 (or 11111111
). This will make the left most 16 bits zero. Only the 8 right most bits could possibly line up with our 255. The result will be 01001000
or 72.
For the green colour we need to do both things - shift over 8 bits and then AND the right most 8 bits with 11111111
(255). The green portion 00111110
is 62.
So, the RGB version of 00011001 00111110 01001000
is rgb(25, 62, 72).
# Codepen Samples
Here are some CodePens using the Bitwise operators.
# Generating a Random Colour, Displaying it in RGB with Contrasting Text
# Converting from HEX to decimal numbers for Colours
Codepen calculating Odd and Even (opens new window) - open this one in a new page and open the development tools console to see the results.
A practical use for Bitwise operators, beyond calculating odd or even, is saving user permissions inside a single number.
MDN reference for Bitwise operators (opens new window)
# What to do this week
TODO
Things to do before next week.
- Read all the content from
Modules 3.1, 3.2, and 4.1
. - Continue working on the Hybrid Exercises
- Submit Hybrid 1