How to simplify modulus arithmetic? - javascript

I have
let f = x => x % 4 === 0 ? 0 : 4 - x % 4
But that's a piece of garbage function. Help.
x is never going to be negative.
Here's a sort of Table of Truth, or something.
x x % 4 4 - (x % 4) f(x)
0 0 4 0
1 1 3 3
2 2 2 2
3 3 1 1
4 0 4 0
5 1 3 3
6 2 2 2
7 3 1 1
8 0 4 0
9 1 3 3
I'm trying to find some correlations here, but it's late and I don't think my brain is working correctly. zzz
What I'm seeing in the f(x) column is a sort of reverse modulus, whereby the outputs cycle from 032103210... instead of 01230123...
I'm sensing some use of Math.max or Math.min in combination with Math.abs might help … There's probably an x * -1 in there somewhere too …
Can you help me write f such that it doesn't suck so badly ?

Moving Redu's use of bitwise operators a bit ahead:
f(x) = -x & 3
Table of Truths™
x x -x 3 -x&3 -x&3
- ---- ----- ---- ---- ----
0 0000 0000 0011 0000 0
1 0001 -0001 0011 0011 3
2 0010 -0010 0011 0010 2
3 0011 -0011 0011 0001 1
4 0100 -0100 0011 0000 0
5 0101 -0101 0011 0011 3
6 0110 -0110 0011 0010 2
7 0111 -0111 0011 0001 1
8 1000 -1000 0011 0000 0
9 1001 -1001 0011 0011 3
var i,
f = x => -x & 3;
for (i = 0; i < 20; i++) {
console.log(i, f(i));
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Original solution with negative value and a negative offset of 3 then modulo and add the same offset again.
f(x) = (-x - 3) % 4 + 3
var i,
f = x => (-x - 3) % 4 + 3;
for (i = 0; i < 20; i++) {
console.log(i, f(i));
}
.as-console-wrapper { max-height: 100% !important; top: 0; }

Something like this will definitely do:
(4 - (x % 4)) % 4
Here's some more truth:
x x % 4 4 - (x % 4) (4 - (x % 4)) % 4
0 0 4 0
1 1 3 3
2 2 2 2
3 3 1 1
4 0 4 0
5 1 3 3
6 2 2 2
7 3 1 1
8 0 4 0
9 1 3 3

I thought you don't want to use modulo. Then here is your code.
var f = x => 2 * (x & 2 ? ~x & 1 : x & 1) + (x & 1)
x x % 4 4 - (x % 4) f(x)
0 0 4 0
1 1 3 3
2 2 2 2
3 3 1 1
4 0 4 0
5 1 3 3
6 2 2 2
7 3 1 1
8 0 4 0
9 1 3 3
Explanation: I just had to recall the back old days of truth tables which helped me to solve out this problem. So now we have inputs and output. Since we work in modulo 4 we are interested only in the last two bits.
Input Output
0 : 0 0 0 0
1 : 0 1 1 1
2 : 1 0 1 0
3 : 1 1 0 1
So if we look, the output 2^1 digit is XOR of input 2^0 and 2^1 hence 2 * (x & 2 ? ~x & 1 : x & 1) and the output 2^0 digit is in fact input 2^0 digit. Which is (x & 1) hence... var f = x => 2 * (x & 2 ? ~x & 1 : x & 1) + (x & 1)
Note: (foo XOR bar = foo ? !bar : bar)
u v
y z z w
x x & 2 ? ~x y & 1 x & 1 2 * z w + v f(x)
-- ------ ------ --- ------- ------ ------ ----- ----- ----
0 0000 0000 F -0001 0001 0000 0 0 0
1 0001 0000 F -0010 0000 0001 2 3 3
2 0010 0010 T -0011 0001 0000 2 2 2
3 0011 0010 T -0100 0000 0001 0 1 1
4 0100 0000 F -0101 0001 0000 0 0 0
5 0101 0000 F -0110 0000 0001 2 3 3
7 0110 0010 T -0111 0001 0000 2 2 2
8 0111 0010 T -1000 0000 0001 0 1 1
9 1000 0000 F -1001 0001 0000 0 0 0

Related

Why does -3 >> 1 equal -2?

In JS, we have the following situation:
<< operator:
3 << 1 // 6
5 << 1 // 10
7 << 1 // 14
-3 << 1 // -6
-5 << 1 // -10
-7 << 1 // -14
>> operator:
3 >> 1 // 1
5 >> 1 // 2
7 >> 1 // 3
-3 >> 1 // -2
-5 >> 1 // -3
-7 >> 1 // -4
As you can see, for the << operator, and for values less than 2**32, we have abs(X << Y) === abs(-X << Y).
Why doesn't this keep true for the >> operator?
Because you are rotating the binary representation of those numbers. And the negative numbers are stored as 2's complement binary
So (using just 8-bits for illustration purposes):
-3 = 11111101
Which if you rotate with >> which is sign propagating you will get:
11111110 = -2
Because the sign propagating shift copies the sign bit to the left-most bit.
With the positive numbers it's easier:
3 = 00000011
After shifting with >> (since it's positive, you are shifting in zeros)
00000001 = 1
It's because minus has greater precedence than shift operator.
So, -3 >> 1 will run as (-3) >> (1) but not as -(3 >> 1).

positive/negative Modulo to get items in range

I looked at https://math.stackexchange.com/questions/519845/modulo-of-a-negative-number and Modulo operation with negative numbers but I still wonder how to use a negative modulo value to get items in a range.
Here is a simplified use case before my question bellow, I have a slideshow with 3 slides (slidesCount = 3):
slide indexes: 0 1 2
Now I would like to access the right slide from these numbers:
-2 -1 0 1 2 3 4
should match slide:
1 2 0 1 2 0 1
So with index % slidesCount I cover the cases:
0 1 2 3 4
but not negative values. -1 % 3 returns -1 so is slidesCount + index % slidesCount the correct expression if index is negative?
First of, is there a simpler/smarter way to write:
index = index % slidesCount + (index < 0 ? slidesCount : 0)
Now my question is for a slideshow of 3 visible items per slide,
where the last slide may have only one item (index 9 bellow) so from these numbers:
-3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
I want to match slides:
9 0 3 6 9 0
I hope the following diagram makes sense! Please help me get the correct equation out of it with minimum ifs:
-3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
|________| |______________________________________________|
|| || ||
|| Math.floor( i / visibleSlides )
Math.ceil(i / visibleSlides) || ||
|| || ||
\/ \/ \/
-1 0 1 2 3 4
|___| |_______________________| |___|
|| || ||
slidesCnt + i % visibleSlides i % visibleSlides || ??
|| || ||
\/ \/ \/
3 0 1 2 3 0
|| i * visibleSlides
\/
9 0 3 6 9 0
in the end, this is how I solved the problem:
// Prevents out of range.
// e.g. -1, -2, 12, 13
let newIndex = (index + slidesCount) % slidesCount
// Calculates how many items are missing on last slide.
// e.g. if 10 slides with 3 visible slides, 2 missing slides on last slide.
let lastSlideItems = slidesCount % visibleSlides || visibleSlides
let missingItems = visibleSlides - lastSlideItems
// If index is negative adjust by adding the missing slides.
newIndex += index < 0 ? missingItems : 0
// Always get the first item of the series of visible items.
// e.g. if index is 8 and 3 visible slides, newIndex will be 6.
newIndex = Math.floor(newIndex / visibleSlides) * visibleSlides

Trouble figuring out Javascript & operator

So I am new to Javascript, in my first Intro to Javascript class. I just found what the & operator does and came across this definition:
The & operator returns a one in each bit position for which the corresponding bits of both operands are ones.
I was also able to find descriptions of == and === on this website on a question that has been previously answered. On this link here: Wikipedia Bitwise_operation#AND
It explains that 1 & 1 is the same as 1 x 1, simple multiplication. So my question is then why is 10 & 5 == 0 and 10 & 6 == 2
Wouldn't it be 10 & 5 == 50 and 10 & 6 == 60?
What am I failing to understand?
It's only the binary bits in each position (the 1s and 0s) that are multiplied.
For example, with 10 & 5:
10 = 1010 in binary
5 = 0101 in binary
Now multiply each digit against the other digit in the same position:
(1 x 0) (0 x 1) (1 x 0) (0 x 1)
= 0000
= 0 in decimal
console.log(10 & 5)
With 10 & 6:
10 = 1010 in binary
6 = 0110 in binary
Now multiply each digit against the other digit in the same position:
(1 x 0) (0 x 1) (1 x 1) (0 x 0)
= 0010
= 2 in decimal
console.log(10 & 6)
It’s equivalent to multiplication per bit.
0 & 0 === 0
0 & 1 === 0
1 & 1 === 1
So your example of 10 & 5 is:
1010
& 0101
= 0000
If you switch from base 10 to base 2, which is required when comparing numbers bitwise, then it is clearer :
10 & 5 becomes 1010 & 0101 which equals 0000 in base 2, 0 in base 10
10 & 6 becomes 1010 & 0110 which equals 0010 in base 2, 2 in base 10
Hope this helps!
So 10 should be something like this 1010
and 5 should be something like this 0101
Now, if you find & or And for both of them, You should get something like 0000 which is zero
Similarly for 6, it should be 0110
which should give & or And for both of them as 0010 which happens to be 2
Note: for And we have the following rule
0 & 0 === 0
0 & 1 === 0
1 & 1 === 1
Try going through w3c article: https://www.w3schools.com/jsref/jsref_operators.asp

Why and 1 ( &1) bitwise operation always return 0 or 1

I just started learning about bit wise operation and want to ask why and 1 ( &1) bitwise operation always return 0 or 1 .
0 & 0 === 0
0 & 1 === 0
1 & 0 === 0
1 & 1 === 1
therefore any number & 1 will always be either 0 or 1
in binary ... any number
xxxxxxxxxxxxx0
or
xxxxxxxxxxxxx1
where x can be 0 or 1
1 in binary is
00000000000001
so
xxxxxxxxxxxxx1 &
00000000000001 ==
00000000000001
xxxxxxxxxxxxx0 &
00000000000001 ==
00000000000000
When you perform a & 1 it will always return 0 or 1 depending upon the the last binary digit of a.
Rules:
0 & 0 = 0
0 & 1 = 0
1 & 1 = 1
For example:
a = 5 //5 = 0101
b = a & 1 = 1 //(0101 & 0001)
a = 6 //6 = 0110
b = a & 1 = 0 //(0110 & 0001)
This is a bitwise operation. Suppose you take 2 & 1. That would be 10 and 01 in binary. Bitwise AND will give 00. BitWise operations with 1 will give 1 or 0 always because 1 has only a significant unit's place in binary. So it cannot return any value other than a 0 or a 1.
This can be used to check if an integer is odd or even, returning a 0 for False and 1 for True.
is_odd: 1 for odd , 0 for even
odd = number & 1
is_even: 1 for even , 0 for odd
even = number & 1 ^ 1

Reverse a percentage

I have a percentage, it ranges from 50% to 0%.
I need the values to be mirrored, so:
0% now equals 50%
1% = 49%
25% = 25%
48% = 2%
50% = 0%
etc.
Thanks for any help!
You can use j = max_i - i + min_i where the two constants min_i and max_i are the lower and upper limit of the range.
If i is always between 0 and 50 then you can just write j = 50 - i.
It looks like you want to define a function like this:
(x) f(x)
0 50
1 49
2 48
: :
48 2
49 1
50 0
Then the function is simply:
f(x) = 50 - x
More generally, if x is between low and high inclusive, then:
f(x) = (high + low) - x
Other functions of interest
Here are some other common functions:
(x) f(x)___
0 0 |
1 0 3
2 0 ___|
3 1 |
4 1 3 f(x) = x / 3
5 1 ___| where / is integer division
6 2 |
7 2 3
: : ___|
(x) f(x)___
0 0 |
1 1 3
2 2 ___|
3 0 |
4 1 3 f(x) = x % 3
5 2 ___| where % is integer remainder
6 0 |
7 1 3
: : ___|
Both of the above are sometimes combined when indexing a 2-dimensional table:
______4 columns______
/ \
_______________________ (x) row(x) col(x)
| | | | | 0 0 0
| 0 | 1 | 2 | 3 | 1 0 1
|_____|_____|_____|_____| 2 0 2 row(x) = x / 4
| | | | | 3 0 3 col(x) = x % 4
| 4 | 5 | 6 | 7 | 4 1 0
|_____|_____|_____|_____| 5 1 1 x = row(x) * 4 + col(x)
| | | | 6 1 2
| 8 | 9 | ... | 7 1 3
|_____|_____|_____| : : :
If i'm reading that correctly, the only way for the pcntAnimationComplt to go down is if your currImgWidth is decreasing. If that is so, then just do this:
pcntAnimationComplt = 50 - Math.round((parseFloat(currImgWidth / pageWidth) * 100) / 2);
This should go from 0 to 50, as per your requirements.
var min=1;
var max=50;
for(var i=min;i<=max;i++){document.writeln(i + "<br>");}
for(var i=max;i>=min;i--){document.writeln(i + "<br>");}

Categories