Thanks, everyone for expanding on things. I didn't have time to flesh things out and had to be brief. Thanks for filling in the blanks. A lot of comments here on speed. Definitely a good point. Most of the time, I'm optimizing for my time and for code quality/readability rather than the computer's time, but if you have a scenario where every cycle counts the if-statement could be faster-depending on how branch prediction works.
One thing I notice in the vid is the trailing comma before the ] character, that's ugly, you coulda just created variable, set it to '[' then started your loop prefixing the variable's character instead of suffixing in the comma, on each loop after printing the variable's character you just set it to a comma instead, on the 1st loop you get the expected [ then on every number thereafter you get a , instead, this method avoids branching inside the loop and remains simple to read, alternatively could alter your current loop to use the comparison result to cancel/include a value: ',' + ((i == (ARRAY_LENGTH - 1)) * (']' - ',')) or ']' - ((i < (ARRAY_LENGTH - 1)) * (']' - ',' )) I prefer the variable method though as A. it is more readable and likely easier for noobs to understand & B. The compiler would likely devolve the variable to a register and use just one instruction unlike the minimum of 2 instructions the other method generates
Whether optimizing for time or performance matters more is almost always a function of what the code is intended to be used for, i find it very disturbing that people seem to either take one side or the other when that is the wrong question to begin with, the question is on a per project basis which is more important and even then there is usually a clear method on how to get to the most performant option spending the least amount of dev time to reach it.
Fun fact, if you're programming a deck of cards and enumerating them as such: ACE_OF_SPADES = 0, ACE_OF_HEARTS = 1, ... until value of 51, the % operator can be used to find the suit In this case if it's spades, (value % 4) is 0, 1 if it's hearts, 2 if it's clubs and 3 if it's diamonds To think some would regard it as useless is shocking!
Could you (or someone) write a simple example in code that demonstrates this? I'm not following what you mean by "store a + bn in a variable." Is this where 'a' and 'b' are variables and 'n' is any arbitrary number? Nor am I understanding what "a,b" means in that comparison formula. I suppose I'm missing the mathematical formula syntax to grasp these things.
@@TroyNiemeier An easy way to explain what he said is to use a practical example that uses the principle in mind. The example he gives can quite literally be used to convert between X and Y values on a 2D array and a single index. You would need this if you do not want a 2D array and would rather store it in one array with rows*cols size. You can essentially compact down both x and y values into a single number. index = x + y*col. Imagine that when you count up from x, you get the number of columns. So if you increment y by 1, you move by 1 whole row down. To get the x and y values back is a trivial task. x = index % col and y = floor(index / cols). The number of columns is our width. So there is a theoretical infinite number of rows we can have, because none of the formulas use the number of rows. You can even compact a 3d array with an x, y and z using modulo.
3:55 I'd argue that this is by far the more readable way for experienced programmers. If I see that index is something modulo ARRAY_LENGTH, I know that it's always going to be smaller than ARRAY_LENGTH. If I see that there's some comparisons and mutations involving index somehow, I have to actually read through them, ponder edge conditions, etc. in order to know what range it'll be in.
This. I wanted to comment this. As a (maybe fake) beginner with Godot game engine, when I need a random value from the array l, the standard way to access it is l[randi()%len(l)] with python-like index access and randi() being the "random integer" function from Godot's RNG API.
It's definitely the easiest way to do it, but I was reading the .h file for the random functions and it says in big neon lights not to use modulo to set range in Rand. And after reading up on different random algorithms, they all say the same. I think it's because 0 will return 0 in addition to the other end of the range. So, on a large enough set of numbers, the distribution won't be random.
@@SimonJentzschX7 I only found out about it just recently after a foray into pseudo rngs and even then just being plain nosy in the include files. Lol.
One of many uses: Unordered maps and unordered sets, as hash tables. The index for storage and lookup is determined by defining a hash function which returns an unsigned integer, and then that is MODULOED by the total capacity of a given array and then a key/value is stored at that location for an unordered map, or just a key (which is also it's own value) for an unordered set. But if the location is not empty on storage, either the next empty index is available or a linked list is formed off that index. Upon retrieval, the same approach is used, except, instead of looking to see if a spot is empty, it looks to see if the spot matches the key, if not it is either searched down the linked list off that index, if one is there, and then to the right, one index at a time until a matching key is found. When the hashtable gets too full, a new one is allocated with a much bigger capacity, and all the old table are reassigned places in the new hashtable, and then the old hashtable is destroyed.
I usually explain it as subtracting by the right-hand side as much as possible without going below zero. Then it feels more intuitive to use for something like the circular list example.
Quick little trivia to the % operator in C. It actually isn't a mathematically modulo operation but a symmetric modulo operation. If you want to manipulate negative numbers mathematically correct you can still use the symmetric operator. If you want to make sure that you have the mathematically correct output you should either calculate it int a, b; ((a % b) + b) % b like this, or write a function that takes care of this calculation. I personally use a function since it looks cleaner and is easier to understand for others. I usually call the function mod int mod(int a, int b){ int res; res = ((a % b) + b) % b; return res; } Just want to let people know who have trouble with the % operator because of negative values. This function served me well in many cases where I have to actually calculate the mathematical definition of modulo.
As a newbiew to C I saw it's usefulness quite quickly when going through the K&R C book (2nd ed) and in the examples you can find online for it's exercises the modulus operator appears early on and it's usage is apparent.
Pro tip: if you use the formula below the circular buffer will work in both directions, incrementing and decrementing: index = (ARRAY_LENGTH + index + inc_or_dec) % ARRAY_LENGTH Suppose ARRAY_LENGTH is 3, index is 0 and inc_or_dec is 1. Then: index = (3 + 0 + 1) % 3 = 4 % 3 = 1 index = (3 + 1 + 1) % 3 = 5 % 3 = 2 index = (3 + 2 + 1) % 3 = 6 % 3 = 0 Now, suppose index is 2 and inc_or_dec is -1, because we want to do it in reverse order. Then: index = (3 + 2 + -1) % 3 = 4 % 3 = 1 index = (3 + 1 + -1) % 3 = 3 % 3 = 0 index = (3 + 0 + -1) % 3 = 2 % 3 = 2 Works like a charm! I've never seen anyone using this formula. I've managed to figure it out myself.
nice to see a new video so soon! i use the mod usually when i need to align byte arrays or when reading large number of lines into a buffer. it also comes in handy when we need to make sure something is word aligned in memory. it also gets kind of messy when we need to create a buffer that is large enough but not too large, and then it turns into some aweful calculation with bit shifting to both sides and modolus on 31 for some reason. plain mess. however, I remember hearing that the mod operator is expensive to use, is this true? and could you do a video about the circular list data structure and all the tricks to check if it's empty?
Yeah, when you say "circular list", do you mean an array managed in a circular fashion (like I used in the video) or a circular linked list? Regardless, I can add it to the ever-expanding list of future videos.
You didn't really explain corner cases for the operator: first, there are variants for floating point numbers in some languages, but not all; second, different languages behave differently in the case of negative numbers being used. Also, you could have generalized that modulo operator can be used in many cases with wrapping and periodic behaviours.
Yep in C the % operator is handling negative numbers mathematically incorrect for example, I just run into that problem and it was quite frustating because it took me ages to realize where the source of the bug was.
Hello guys. I understand what modulo is it's basically the left over in things that are divided unevenly but what I don't get is why it can for example know things i cant explain. the problem is : It is possible to name the days 0 through 6 where day 0 is Sunday and day 6 is Saturday. If you go on a wonderful holiday leaving on day number 3 (a Wednesday) and you return home after 10 nights you would return home on a Saturday (day 6) Write a general version of the program which asks for the starting day number, and the length of your stay, and it will tell you the number of day of the week you will return on. leave_date = int(input("enter the date you left")) stay_length = int(input("enter the days you were gone")) arrive_date = leave_date + stay_length % 7 print(arrive_date) I don't get how modulo can calculate othe day i will return by knowing the remainder. like how can it know that i will be back by day 6 by only knowing the remainder of a number. like how does it do that? im sorry i feel really dumb i can't explain how please help me im very confused
Think of the days of the week as a loop or ring. Go forward 7 and you end up back where you started, right? Ok. So, if it's day D and you take a trip for N days. If N % 7 == 0, then that means your trip was an even number of weeks (times through the loop) which means that the day of the week doesn't change. If you left on day 2, you get back on day 2. The number of complete weeks doesn't change the day of the week. But the number of extra days (the remainder) does change the day of the week. So, if you leave on day 5, and N == 1, then (5 + 1) % 7 is just 6. If N == 8, then (5 + 8) % 7 is also 6. The extra time around the loop didn't change the outcome. I hope that helps.
Is someone a programmer if they don't know what MOD is? A few decades ago in my country, the Chinese remainder theorem (the generalized version to a ring, with coprime ideals ...)'s DEMONSTRATION was still demanded of students ...last year of high school. Year by year IQ goes down. I was stunned because % isn't a mod operator but a remainder operator, which makes it worthless in most 'mod'-like instructions (loops that go past iList.Count and restart from the start (when you have to to write i - 1)). My own public static float Mod(this float a, float b) => a >= 0 ? a % b : (a % b + b) % b; is probably and by far the most referenced among all custom methods I use.
Let’s say I have an infinite number of baskets. Each basket can carry 10 apples - no more, no less. I have 23 apples. How many apples will remain after I fill the baskets? 10 fits into 20 twice, that’s 2 baskets filled, so we’re left with 3 apples. 23 % 10 = 3 What if I had 4 apples? 10 apples per basket - no more, no less. Since I’m not allowed to put the apples in the basket, I’ll have 4 apples remaining 4 % 10 = 4
% is very useful. i don't know how much for europeans, but for americans should be very useful. and I say that because we have metric system. consider this issue. you have a number of seconds since moment X. let's say when unix time started. so you want to find out how many years, days, hours, minutes passed since then, and seconds. like time since unix time started: this much in years, bla bla. to find out seconds, you just do modulus 60. to find out minutes, you do int seconds/60. and I say americans, because, let's say you have a database of heights of people in inches. europeans and everyone else, divides by 10, but americans divide by 12, so you have (int) (inches/12) = feet, and_inches=height%12. we don't think often about it, but metric system really helps. and modulus helps. Another example I can think of is when you can't control a really large number, and want smaller fraction of it. Like in bash, bash offers a great feature like: echo ${RANDOM} and it offers a number between 0 and 65535. But lets say that is too big for you. And just want a random number of seconds that is within a minute. So what you do is do RANDOM % 60. and the remainder will be smaller than 60. And I imagine is very useful in cryptography. Prime numbers. I don't know for sure, because I don't work in that field, but I have a feeling.
Thanks, everyone for expanding on things. I didn't have time to flesh things out and had to be brief. Thanks for filling in the blanks.
A lot of comments here on speed. Definitely a good point. Most of the time, I'm optimizing for my time and for code quality/readability rather than the computer's time, but if you have a scenario where every cycle counts the if-statement could be faster-depending on how branch prediction works.
One thing I notice in the vid is the trailing comma before the ] character, that's ugly, you coulda just created variable, set it to '[' then started your loop prefixing the variable's character instead of suffixing in the comma, on each loop after printing the variable's character you just set it to a comma instead, on the 1st loop you get the expected [ then on every number thereafter you get a , instead, this method avoids branching inside the loop and remains simple to read, alternatively could alter your current loop to use the comparison result to cancel/include a value:
',' + ((i == (ARRAY_LENGTH - 1)) * (']' - ','))
or
']' - ((i < (ARRAY_LENGTH - 1)) * (']' - ',' ))
I prefer the variable method though as
A. it is more readable and likely easier for noobs to understand &
B. The compiler would likely devolve the variable to a register and use just one instruction unlike the minimum of 2 instructions the other method generates
Whether optimizing for time or performance matters more is almost always a function of what the code is intended to be used for, i find it very disturbing that people seem to either take one side or the other when that is the wrong question to begin with, the question is on a per project basis which is more important and even then there is usually a clear method on how to get to the most performant option spending the least amount of dev time to reach it.
Fun fact, if you're programming a deck of cards and enumerating them as such: ACE_OF_SPADES = 0, ACE_OF_HEARTS = 1, ... until value of 51, the % operator can be used to find the suit
In this case if it's spades, (value % 4) is 0, 1 if it's hearts, 2 if it's clubs and 3 if it's diamonds
To think some would regard it as useless is shocking!
% is useful to store two values simultaneously. If you store a + bn in a variable (0
Could you (or someone) write a simple example in code that demonstrates this? I'm not following what you mean by "store a + bn in a variable." Is this where 'a' and 'b' are variables and 'n' is any arbitrary number? Nor am I understanding what "a,b" means in that comparison formula. I suppose I'm missing the mathematical formula syntax to grasp these things.
@@TroyNiemeier An easy way to explain what he said is to use a practical example that uses the principle in mind. The example he gives can quite literally be used to convert between X and Y values on a 2D array and a single index. You would need this if you do not want a 2D array and would rather store it in one array with rows*cols size. You can essentially compact down both x and y values into a single number. index = x + y*col. Imagine that when you count up from x, you get the number of columns. So if you increment y by 1, you move by 1 whole row down. To get the x and y values back is a trivial task. x = index % col and y = floor(index / cols). The number of columns is our width. So there is a theoretical infinite number of rows we can have, because none of the formulas use the number of rows. You can even compact a 3d array with an x, y and z using modulo.
3:55 I'd argue that this is by far the more readable way for experienced programmers. If I see that index is something modulo ARRAY_LENGTH, I know that it's always going to be smaller than ARRAY_LENGTH. If I see that there's some comparisons and mutations involving index somehow, I have to actually read through them, ponder edge conditions, etc. in order to know what range it'll be in.
That's fair. I think it's one of those things where it's really clear once you understand it. Until then, it's pretty confusing and intimidating.
also use it to separate digits from a number
Very useful for making a concatenator and deconcatenator
I use the mod a lot especiall when creating random values like rand() % range.
Me too. Thanks.
This. I wanted to comment this. As a (maybe fake) beginner with Godot game engine, when I need a random value from the array l, the standard way to access it is l[randi()%len(l)] with python-like index access and randi() being the "random integer" function from Godot's RNG API.
It's definitely the easiest way to do it, but I was reading the .h file for the random functions and it says in big neon lights not to use modulo to set range in Rand. And after reading up on different random algorithms, they all say the same. I think it's because 0 will return 0 in addition to the other end of the range. So, on a large enough set of numbers, the distribution won't be random.
@@jacksonbrim7359 You have a good point there and yes I should have read the the header file a little bit more carefully. Thanks.
@@SimonJentzschX7 I only found out about it just recently after a foray into pseudo rngs and even then just being plain nosy in the include files. Lol.
One of many uses: Unordered maps and unordered sets, as hash tables. The index for storage and lookup is determined by defining a hash function which returns an unsigned integer, and then that is MODULOED by the total capacity of a given array and then a key/value is stored at that location for an unordered map, or just a key (which is also it's own value) for an unordered set. But if the location is not empty on storage, either the next empty index is available or a linked list is formed off that index. Upon retrieval, the same approach is used, except, instead of looking to see if a spot is empty, it looks to see if the spot matches the key, if not it is either searched down the linked list off that index, if one is there, and then to the right, one index at a time until a matching key is found. When the hashtable gets too full, a new one is allocated with a much bigger capacity, and all the old table are reassigned places in the new hashtable, and then the old hashtable is destroyed.
The intro beat though❤🔥
As a programmer with no math skills, this is a wild concept to wrap my head around, but also very useful. Thank you.
I usually explain it as subtracting by the right-hand side as much as possible without going below zero. Then it feels more intuitive to use for something like the circular list example.
Peterolen That’s very true
@Peterolen Not in python
@Peterolen you can access negative indexes in a list in python though
That's just what a remainder is though
Hello, i use % a lot for my diploma thesis where i am implementing RSA and El Gamal encryption in embedded nodes .I am a final yr student in EE.
Quick little trivia to the % operator in C. It actually isn't a mathematically modulo operation but a symmetric modulo operation. If you want to manipulate negative numbers mathematically correct you can still use the symmetric operator. If you want to make sure that you have the mathematically correct output you should either calculate it
int a, b;
((a % b) + b) % b
like this, or write a function that takes care of this calculation. I personally use a function since it looks cleaner and is easier to understand for others.
I usually call the function mod
int mod(int a, int b){
int res;
res = ((a % b) + b) % b;
return res;
}
Just want to let people know who have trouble with the % operator because of negative values. This function served me well in many cases where I have to actually calculate the mathematical definition of modulo.
As a newbiew to C I saw it's usefulness quite quickly when going through the K&R C book (2nd ed) and in the examples you can find online for it's exercises the modulus operator appears early on and it's usage is apparent.
thanks a lot ... you brought back love For C 😍
The main use for it that I have used is for print intervals. Say every 1,000 transactions, do some logging. Where you want logging but not too much.
Way to go brother. I got my 2 week sober chip yesturday.
In the first case I'd usually just check the type of the output. If it is a float then its not even. If its an int then its even
When converting an array to and from a multidimensional array of set dimensions, you also use modulo
Thanks for easy explanation 😃👍
Pro tip: if you use the formula below the circular buffer will work in both directions, incrementing and decrementing:
index = (ARRAY_LENGTH + index + inc_or_dec) % ARRAY_LENGTH
Suppose ARRAY_LENGTH is 3, index is 0 and inc_or_dec is 1. Then:
index = (3 + 0 + 1) % 3 = 4 % 3 = 1
index = (3 + 1 + 1) % 3 = 5 % 3 = 2
index = (3 + 2 + 1) % 3 = 6 % 3 = 0
Now, suppose index is 2 and inc_or_dec is -1, because we want to do it in reverse order. Then:
index = (3 + 2 + -1) % 3 = 4 % 3 = 1
index = (3 + 1 + -1) % 3 = 3 % 3 = 0
index = (3 + 0 + -1) % 3 = 2 % 3 = 2
Works like a charm! I've never seen anyone using this formula. I've managed to figure it out myself.
The classic example is Euclid's Algorithm. And you don't get much more classic than an algorithm that's been in use for well over two thousand years!
nice to see a new video so soon!
i use the mod usually when i need to align byte arrays or when reading large number of lines into a buffer. it also comes in handy when we need to make sure something is word aligned in memory. it also gets kind of messy when we need to create a buffer that is large enough but not too large, and then it turns into some aweful calculation with bit shifting to both sides and modolus on 31 for some reason. plain mess.
however, I remember hearing that the mod operator is expensive to use, is this true? and could you do a video about the circular list data structure and all the tricks to check if it's empty?
As far as CPU instructions go, integer division is on the expensive side. But worrying about a few instruction cycles probably isn't worth it.
Yeah, when you say "circular list", do you mean an array managed in a circular fashion (like I used in the video) or a circular linked list? Regardless, I can add it to the ever-expanding list of future videos.
@@JacobSorber
I meant circular buffer, like what you used.
@@benjaminshinar9509 Got it. Thanks.
could be used in the process of converting numbers from one numeral system to another.
"ohhhhh... [when was the last time I needed that]"? LMFAO!!!!!!! exactly my reaction!!!
Man 😭😭. May you live more than 100 years.
Thanks. I'm not sure I want to live quite that long, but thanks.
@@JacobSorber living long will probably be a curse than a jackpot.
Death isn't much scary though.
But isn't division more expensive than comparison? Especially in context of buffers, where we want maximum performance?
I use mod to arrange prints to a neatly readable format.
You didn't really explain corner cases for the operator: first, there are variants for floating point numbers in some languages, but not all; second, different languages behave differently in the case of negative numbers being used.
Also, you could have generalized that modulo operator can be used in many cases with wrapping and periodic behaviours.
Yep in C the % operator is handling negative numbers mathematically incorrect for example, I just run into that problem and it was quite frustating because it took me ages to realize where the source of the bug was.
Couldn't help but notice the Climbodia shirt. Been to Kampot, eh? ;)
Yep. There's actually some Climbodia/Kampot footage in one of my videos. I used to live in ស្រុកខ្មែរ. Can't wait to get back.
"You had me at 'modulo' ".
Hello guys. I understand what modulo is it's basically the left over in things that are divided unevenly but what I don't get is why it can for example know things i cant explain.
the problem is :
It is possible to name the days 0 through 6 where day 0 is Sunday and day 6 is Saturday. If you go on a wonderful holiday leaving on day number 3 (a Wednesday) and you return home after 10 nights you would return home on a Saturday (day 6) Write a general version of the program which asks for the starting day number, and the length of your stay, and it will tell you the number of day of the week you will return on.
leave_date = int(input("enter the date you left"))
stay_length = int(input("enter the days you were gone"))
arrive_date = leave_date + stay_length % 7
print(arrive_date)
I don't get how modulo can calculate othe day i will return by knowing the remainder. like how can it know that i will be back by day 6 by only knowing the remainder of a number. like how does it do that?
im sorry i feel really dumb i can't explain how please help me im very confused
Think of the days of the week as a loop or ring. Go forward 7 and you end up back where you started, right? Ok. So, if it's day D and you take a trip for N days. If N % 7 == 0, then that means your trip was an even number of weeks (times through the loop) which means that the day of the week doesn't change. If you left on day 2, you get back on day 2. The number of complete weeks doesn't change the day of the week. But the number of extra days (the remainder) does change the day of the week. So, if you leave on day 5, and N == 1, then (5 + 1) % 7 is just 6. If N == 8, then (5 + 8) % 7 is also 6. The extra time around the loop didn't change the outcome. I hope that helps.
Very helpful, thank you!!
Is someone a programmer if they don't know what MOD is? A few decades ago in my country, the Chinese remainder theorem (the generalized version to a ring, with coprime ideals ...)'s DEMONSTRATION was still demanded of students ...last year of high school. Year by year IQ goes down. I was stunned because % isn't a mod operator but a remainder operator, which makes it worthless in most 'mod'-like instructions (loops that go past iList.Count and restart from the start (when you have to to write i - 1)). My own public static float Mod(this float a, float b) => a >= 0 ? a % b : (a % b + b) % b; is probably and by far the most referenced among all custom methods I use.
I used it for the vigenere cipher haha
Interesting, how so?
People who just started: % is useless
Veterans: Spam it everywhere
Never used it other than coding challenging
Let’s say I have an infinite number of baskets. Each basket can carry 10 apples - no more, no less. I have 23 apples. How many apples will remain after I fill the baskets?
10 fits into 20 twice, that’s 2 baskets filled, so we’re left with 3 apples.
23 % 10 = 3
What if I had 4 apples? 10 apples per basket - no more, no less. Since I’m not allowed to put the apples in the basket, I’ll have 4 apples remaining
4 % 10 = 4
0:56 Six mod three is two. 👻
% is very useful. i don't know how much for europeans, but for americans should be very useful. and I say that because we have metric system.
consider this issue. you have a number of seconds since moment X. let's say when unix time started. so you want to find out how many years, days, hours, minutes passed since then, and seconds. like time since unix time started: this much in years, bla bla. to find out seconds, you just do modulus 60. to find out minutes, you do int seconds/60.
and I say americans, because, let's say you have a database of heights of people in inches. europeans and everyone else, divides by 10, but americans divide by 12, so you have (int) (inches/12) = feet, and_inches=height%12. we don't think often about it, but metric system really helps. and modulus helps.
Another example I can think of is when you can't control a really large number, and want smaller fraction of it. Like in bash, bash offers a great feature like:
echo ${RANDOM}
and it offers a number between 0 and 65535. But lets say that is too big for you. And just want a random number of seconds that is within a minute. So what you do is do RANDOM % 60. and the remainder will be smaller than 60.
And I imagine is very useful in cryptography. Prime numbers. I don't know for sure, because I don't work in that field, but I have a feeling.
Very true. Thanks.
Good one
please can you translate english, same word i cant understanded
so when read it maby i get it.
if((x^2 -1)%24==0) then x might be prime;
Is it useful?
Tells me whether or not 2100 will be a leap year...
Sheesh!!
2100 % 4 == 0, so it might be a leap year.
2100 % 100 = 0, so it might not be a leap year.
2100 % 400 = 100, it it will _not_ be a leap year.