-
-
Notifications
You must be signed in to change notification settings - Fork 111
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add bitwise concept #722
base: main
Are you sure you want to change the base?
Add bitwise concept #722
Changes from all commits
90ed84e
906a767
c925970
52770b9
82e0424
77679ee
cbbe48f
2f18e88
2d5dea3
9a17e1c
6e4d3f3
f8fca1a
b073b12
54545de
b0cf475
7d00134
aa79d27
ce39d30
fc09e07
e76389a
6ceb47f
40ad002
6a60cab
662f383
d7cfa4b
0ca8335
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"authors": [ | ||
"stewartmurrie" | ||
], | ||
"contributors": ["jiegillet"], | ||
"blurb": "Learn how to use integer bitwise operations in Elm" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
# About | ||
|
||
## Bitwise operations | ||
|
||
Bitwise operations allow us to manipulate individual digits within binary numbers. | ||
These operations are fundamental in computing, providing an efficient way to perform low-level tasks, such as controlling specific bits in memory, optimizing mathematical calculations, encryption, communications, and encoding/decoding data. | ||
|
||
### Understanding 32-bit Integers in Elm | ||
|
||
In Elm, integers are stored as 32-bit signed integers using [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) representation, meaning they use 32 binary digits (_bits_) to store each integer value. | ||
This bit limit affects the range of integers that Elm can represent directly: | ||
|
||
Positive Range: 0 to 2<sup>31</sup> - 1 (or 0 to 2,147,483,647) | ||
Negative Range: -2<sup>31</sup> to -1 (or -2,147,483,648 to -1). | ||
|
||
For example, the integer `5` is represented in binary as `00000000000000000000000000000101`, although usually we ignore the leading zeros and just say `101`. | ||
|
||
### Bitwise operations | ||
|
||
Elm provides several bitwise operators in its [Bitwise module](https://package.elm-lang.org/packages/elm/core/latest/Bitwise) | ||
|
||
### Basic operations | ||
|
||
Modifying individual bits of a number is called _masking_. | ||
A _mask_ is a number where specific bits have been set in a particular way to manipulate another number using bitwise operators such as `and`, `or`, and `xor`. | ||
|
||
#### and | ||
|
||
`and` combines two numbers by keeping only the bits that are `1` in both. | ||
This is useful for checking to see if an individual bit is set. | ||
For example, to check if the 4th bit of a number is set to `1`, `and` it with a mask of `01000` (`8` in decimal) and see if the result is non-zero: | ||
|
||
````elm | ||
Bitwise.and 13 8 --> 8 | ||
-- 13 = 01101 | ||
-- 8 = 01000 | ||
-- and = 01000 = 8 | ||
|
||
|
||
### or | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be a level 4 heading |
||
|
||
`or` combines two numbers by setting each bit to `1` if it is `1` in either or both numbers. | ||
This is useful for setting a specific bit to `1`. | ||
For example, to set the 2nd bit in `10101`, `or` it with the mask `00010`: | ||
|
||
```elm | ||
Bitwise.or 21 2 --> 23 | ||
-- 21 = 10101 | ||
-- 2 = 00010 | ||
-- or = 10111 = 23 | ||
```` | ||
|
||
### Exclusive-or (xor) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be a level 4 heading |
||
|
||
`xor` combines two numbers by setting each bit to `1` if it is `1` in one number but `0` in the other. | ||
This is useful for flipping a bit to its opposite value: | ||
|
||
````elm | ||
Bitwise.xor 21 4 --> 17 | ||
-- 21 = 10101 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be better to use 20 and 5 here, so that you can see that it works both ways round. ( 0 - 1 and 1 - 0 ) |
||
-- 4 = 00100 | ||
-- xor = 10001 = 17 | ||
|
||
#### Complement | ||
|
||
`complement` inverts each bit of a number (`0` becomes `1`, `1` becomes `0`). | ||
|
||
Note that this will result in positive numbers becoming negative, and negative numbers becoming positive. | ||
This is because negative numbers in binary are represented with `1` in the left-most position. | ||
|
||
```elm | ||
Bitwise.complement 21 --> -22 | ||
-- 21 = 00000000000000000000000000010101 | ||
-- complement = 11111111111111111111111111101010 = -22 | ||
```` | ||
|
||
### Bit shifting | ||
|
||
The following operators move bits left or right by a specified number of positions, effectively multiplying or dividing by powers of 2. | ||
|
||
`shiftLeftBy` moves bits to the left, filling in with `0` from the right-hand side. | ||
For example, to shift `21` left by 3 places: | ||
|
||
```elm | ||
Bitwise.shiftLeftBy 3 21 --> 168 | ||
-- 21 = 10101 | ||
-- shiftLeftBy 3 = 10101000 = 168 | ||
``` | ||
|
||
This is the same as saying `21 * 2^3 = 21 * 2 * 2 * 2 = 168` | ||
|
||
`shiftRightBy`: Moves bits to the right: | ||
|
||
```elm | ||
Bitwise.shiftRightBy 2 21 --> 5 | ||
-- 21 = 10101 | ||
-- shiftRightBy 2 = 00101 = 5 | ||
``` | ||
|
||
Shifting to the right by 2 places is the same as integer division by 4. | ||
|
||
Note that this function duplicates whatever value is in the leftmost bit. | ||
So, negative numbers will stay negative: | ||
|
||
```elm | ||
Bitwise.shiftRightBy 3 -21 --> -6 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not what I'm getting from
also |
||
-- -21 = 111...10101 | ||
-- shiftRightBy 3 = 111...11101 = -6 | ||
``` | ||
|
||
If you want to shift right and fill in with zeros, use `shiftRightZfBy`: | ||
|
||
```elm | ||
Bitwise.shiftRightZfBy 3 -21 --> 1073741818 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also not what I'm getting, I get
|
||
-- -21 = 111...10101 | ||
-- shiftRightZfBy 3 = 00111...11101 = 1073741818 | ||
``` |
stewartmurrie marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
# Introduction | ||
|
||
Bitwise operations allow us to manipulate individual digits within binary numbers. | ||
|
||
## Bitwise operations | ||
|
||
Elm provides several bitwise operators in its [Bitwise module](https://package.elm-lang.org/packages/elm/core/latest/Bitwise) | ||
|
||
## Basic operations | ||
|
||
Modifying individual bits of a number is called _masking_. | ||
A _mask_ is a number where specific bits have been set in a particular way to manipulate another number using bitwise operators such as `and`, `or`, and `xor`. | ||
|
||
### and | ||
|
||
`and` combines two numbers by keeping only the bits that are `1` in both. | ||
This is useful for checking to see if an individual bit is set. | ||
For example, to check if the 4th bit of a number is set to `1`, `and` it with a mask of `01000` (`8` in decimal) and see if the result is non-zero: | ||
|
||
````elm | ||
Bitwise.and 13 8 --> 8 | ||
-- 13 = 01101 | ||
-- 8 = 01000 | ||
-- and = 01000 = 8 | ||
|
||
|
||
### or | ||
|
||
`or` combines two numbers by setting each bit to `1` if it is `1` in either or both numbers. | ||
This is useful for setting a specific bit to `1`. | ||
For example, to set the 2nd bit in `10101`, `or` it with the mask `00010`: | ||
|
||
```elm | ||
Bitwise.or 21 2 --> 23 | ||
-- 21 = 10101 | ||
-- 2 = 00010 | ||
-- or = 10111 = 23 | ||
```` | ||
|
||
### Exclusive-or (xor) | ||
|
||
`xor` combines two numbers by setting each bit to `1` if it is `1` in one number but `0` in the other. | ||
This is useful for flipping a bit to its opposite value: | ||
|
||
````elm | ||
Bitwise.xor 21 4 --> 17 | ||
-- 21 = 10101 | ||
-- 4 = 00100 | ||
-- xor = 10001 = 17 | ||
|
||
### Complement | ||
|
||
`complement` inverts each bit of a number (`0` becomes `1`, `1` becomes `0`). | ||
|
||
Note that this will result in positive numbers becoming negative, and negative numbers becoming positive. | ||
This is because negative numbers in binary are represented with `1` in the left-most position. | ||
|
||
```elm | ||
Bitwise.complement 21 --> -22 | ||
-- 21 = 00000000000000000000000000010101 | ||
-- complement = 11111111111111111111111111101010 = -22 | ||
```` | ||
|
||
## Bit shifting | ||
|
||
The following operators move bits left or right by a specified number of positions, effectively multiplying or dividing by powers of 2. | ||
|
||
`shiftLeftBy` moves bits to the left, filling in with `0` from the right-hand side. | ||
For example, to shift `21` left by 3 places: | ||
|
||
```elm | ||
Bitwise.shiftLeftBy 3 21 --> 168 | ||
-- 21 = 10101 | ||
-- shiftLeftBy 3 = 10101000 = 168 | ||
``` | ||
|
||
This is the same as saying `21 * 2^3 = 21 * 2 * 2 * 2 = 168` | ||
|
||
`shiftRightBy`: Moves bits to the right: | ||
|
||
```elm | ||
Bitwise.shiftRightBy 2 21 --> 5 | ||
-- 21 = 10101 | ||
-- shiftRightBy 2 = 00101 = 5 | ||
``` | ||
|
||
Shifting to the right by 2 places is the same as integer division by 4. | ||
|
||
Note that this function duplicates whatever value is in the leftmost bit. | ||
So, negative numbers will stay negative: | ||
|
||
```elm | ||
Bitwise.shiftRightBy 3 -21 --> -6 | ||
-- -21 = 111...10101 | ||
-- shiftRightBy 3 = 111...11101 = -6 | ||
``` | ||
|
||
If you want to shift right and fill in with zeros, use `shiftRightZfBy`: | ||
|
||
```elm | ||
Bitwise.shiftRightZfBy 3 -21 --> 1073741818 | ||
-- -21 = 111...10101 | ||
-- shiftRightZfBy 3 = 00111...11101 = 1073741818 | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[ | ||
{ | ||
"url": "https://package.elm-lang.org/packages/elm/core/latest/Bitwise", | ||
"description": "Bitwise module" | ||
}, | ||
{ | ||
"url": "https://guide.elm-lang.org/appendix/types_as_bits", | ||
"description": "Documentation on how Elm represents types as bits" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Hints | ||
stewartmurrie marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
- The documentation for the `Bitwise` package can be found [here][bitwise-docs]. | ||
|
||
## 1. Shift back the bits | ||
|
||
- There are two functions for shifting bits to the right, but [only one][bitwise-shiftRightZfBy] will always insert a 0. | ||
|
||
## 2. Set some bits | ||
|
||
- [One of the bitwise functions][bitwise-or] will always set a bit to 1 where the bits in both values are 1. | ||
|
||
## 3. Flip specific bits | ||
|
||
- There is [a bitwise function][bitwise-xor] that will flip a bit where the mask is 1. | ||
|
||
## 4. Clear specific bits | ||
|
||
- [One of the bitwise functions][bitwise-and] clears bits where the bit in the mask is 0. | ||
- But, you may need to combine it with [another function][bitwise-complement] to clear bits where the mask is 1. | ||
|
||
## 5. Decrypt a message | ||
|
||
- Apply the other functions you wrote to the input in the following order, taking the output of one and using it as the input to the next one: | ||
|
||
1. `setBits` | ||
2. `flipBits` | ||
3. `shiftBack` | ||
4. `clearBits` | ||
|
||
For step 4, you'll need to convert the binary number with the 1st and 5th bits set (10001) to decimal. | ||
|
||
[bitwise-docs]: https://package.elm-lang.org/packages/elm/core/latest/Bitwise | ||
[bitwise-shiftRightZfBy]: https://package.elm-lang.org/packages/elm/core/latest/Bitwise#shiftRightZfBy | ||
[bitwise-or]: https://package.elm-lang.org/packages/elm/core/latest/Bitwise#or | ||
[bitwise-xor]: https://package.elm-lang.org/packages/elm/core/latest/Bitwise#xor | ||
[bitwise-complement]: https://package.elm-lang.org/packages/elm/core/latest/Bitwise#complement | ||
[bitwise-and]: https://package.elm-lang.org/packages/elm/core/latest/Bitwise#and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is an extra blank line here I think