5:58 correction, we don't use a sign bit to represent a number which would result in the existence of 0 and -0 (negative 0), for example 0000 and 1000 in int4, instead we use 2's complement numbers, where essentially we take the leftmost bit and flip it's sign, for example xyzw int4 would equal to 2^0*w + 2^1*z + 2^2*y - 2^3*x (attention to the minus in the equation)
Twos compliment also allows subtraction to be treated exactly like addition, so both can be on the same hardware. And getting the negative of a number is as simple as flipping all the bits and adding 1
@@puddleglum5610 not having a -0 is a bonus, the main benefit is, as you pointed, that you don't need dedicated checks and hardware to deal with negative numbers
@@hwstar9416 No, 1s complement still has the issue that 0 and -0 exist. With one's complement we just invert bits, so 1 as an 8 bit integer is now 0000 0001, making -1 equal to 1111 1110 or the inverted number. This means both 0000 0000 and 1111 1111 are coded as zero. Only with 2s complement is this no longer an issue. And it has the side effect that the MSB still exists, as soon as you reach a maximum value it flips your MSB., Take 8bit integers as an example, we go from 127 or 0111 1111 to -128 or 1000 0000. So the first bit still indicates negative numbers.
Integer sizes also play a major role in networking. Double your integer size and you will double your network usage, and consequent costs, both for transmission of said bytes, and processing/storage on your server. Especially relevant for MMOs.
Just a heads up on a slight inaccuracy: you described the “signed magnitude” representation of signed integers, but modern hardware doesn’t use this. It uses the “two’s compliment” representation. This representation allows for integer addition and subtraction to run on the same hardware, and makes it so taking the negative of a number is as simple as flipping all of the bits of the number and adding 1. Either way, nice refresher on my CS101 course from a few years ago!
he does at least go through and describe the actual representations in the examples, and in the documentation he flashes on the screen it mentions twos complement. but I 100% agree and I was thinking the same thing as soon as he mentioned it. I assume this video was meant to be "eli5" lie-to-children level stuff, in which case I think the explanation was acceptable, if a bit frustrating for someone with a cs background xD
@@alicecubensis1221 To be fair, I don't think Kenny has studied CS (correct me if I'm wrong) so it's kinda hard to expect that he knows of something like this or has ever had to physically draw a full adder. And also he mentioned that he is not a programmer so more power to him, having to remember things like IEEE 754 and little-endian or big O notation is stuff you can barely grasp in a CS degree already.
This video on binary numbers and buffer overflow/underflow is an absolute gem! The explanations were clear and easy to follow, and the real-world applications highlighted throughout made the material relatable and understandable. It's a great resource for anyone looking to deepen their knowledge on the subject matter. Thanks for sharing.
Dude every video you make has something cool and nerdy in it I love it. Thanks for contributing man. I was installing Linux the other day and wound up on your vids. I was learning how to a cook a dessert and wound up on your vids. I was learning about security vulnerabilities and wound up on your vids. You're like a a modern lightweight tech-Da Vinci. That's intended to be a compliment. :)
Your video games to make the subject much more approachable is a great idea. I will be showing this video to my students for sure. Keep up the great work.
I teach adult students. I'm not in the confines of a public education system. It's also a side gig I do to help out people trying to learn programming. My day job is low level networking engineering. I'm currently using rust to build extremely efficient custom networks for applications that have a high volume of traffic.
It's not true, that bigger integers are necessarily slower. Often math on bigger integers is even faster than on smaller ones. The most efficient number is often the one corresponding to the architecture. If you're on a 32 bit system, 32 bit integers are often the fastest, if you're on a 64 bit system, 64 bit integers are often the fastest. But what's more important than that is cache size and alignment. Using bigger numbers might be bad for the cache, using different sizes of integers depending on the use case might be bad for the alignment. The latter is normally optimized by the compiler, so there is empty space between integers, so you don't have the smaller size for using smaller integer sizes for some values, while still using having the overhead of doing math with smaller integer sizes.
Yeah this is a good point. Unless the size of your integer is important (for example if you're working closely with memory or drivers) you should just use a plain old int or unsigned
I don't want to be "that guy" porky, but actually a lot of what we used to be taught about CPU arcitecture (cost of a cache miss, speed of L1/2/3 memory, etc) is no longer true. The CPU holds so much fast cache memory, and the look-ahead branch predictors are so busy all the time, that things like cache alignment are no longer important considerations. Yes you can definitely write a program in C that does the bit packing with padding and alignment just right, but it might actually end up slower because the CPU can't figure out what you're trying to do and wasn't going to do what you asked specifically how you asked for it anyway. Modern computers actually suck TBH.
@@cannaroe1213 Sounds more like an extention of the sloppy 90s attitude that next year's hardware will cover up this year's poor software design. It is true that blind attempts at optimization, by some jr. dev that copy pasta'd their way through school with a teacher from 1985, can often result in hindering both the compiler and machine. However branch prediction, look-ahead prefetching, and large cache are still not magic and simply are forbidden from certain optimizations that might change fundamental parts of the code. eg. The programer may know the variable will never need to be outside of 0-255, but the machine cannot assume this and so cannot reduce a long to a short regardless of the optimizing algorithm or architecture. Nobody here is talking about bitpacking which is a somewhat different concept to alignment of primatives. Maybe some interactive program like a game can be a bit sloppy with relatively large caches; but many backend processes are still dealing with orders of magnitude more data than can be handled by even the largest current gen caches. Vectormath SIMD units are also a thing. (Signed vs unsigned is a bit more complicated, on one hand it is a good way for the compiler to find certain problems and to lock in certain behaviors and parameter requirments without separate validations. On the other hand certain CPUs may be faster with one or the other type of math, but that is a very specific super-tune and should be based on profiling, it would take a heap of int math per second for that difference to be relevent.)
3:24 Should it be *signed*, rather than unsigned? An unsigned 32-bit integer should be able to go up to 4.2bill instead of only 2.1bill, if I'm not mistaken.
It's not a sign bit, it's two's complement. The leftmost bit gets it's magnitude flipped so for example instead of 128 it's -128, so a value of 1000 0000 is -128 (which is why a signed int8 with value 127 will overflow)
This is a solid video, but also a bit of a missed opportunity to explain more about two's complement and the alternatives, and why two's complement is better. In part two, maybe?
The alternatives are signed magnitude, which holds the absolute value in the lower bits, and sets the highest bit if it's negative, and 1's complement, which flips all the bit of the absolute value when the number is negative. 2's complement is a result of observing that the greatest unsigned value plus 1 gives 0 and simply filling things out from there. If 15 + 1 ≡ 0 when ignoring overflow, then logically 15 ≡ -1, which carries over to 14 ≡ -2, 13 ≡ -3, etc. For ease of implementation, the values with the most significant bit set are treated as negative (more specifically, their unsigned interpretation minus 2^n where n is the number of bits), even if this means that --8 ≡ -8. It's better because it's derived from the existing behavior, allowing negative numbers to be treated the same as positive or unsigned numbers in most cases. 1's complement and signed magnitude require special casing addition and subtraction depending on the numbers' signs and relative magnitudes. (Though multiplication is relatively easy for all three, though slightly more complex for 1's complement. Division is annoying for all of them, though truncating division (rounding to 0), which most computers use, is _slightly_ easier with signed-magnitude, though it's also not what many programmers or mathematicians actually want.)
@@angeldude101 Thank you. Could you also explain _why_ the two's complement method of implementing signed numbers in computers is _called_ two's complement? I do sort of understand _how_ the so-called "two's complement" system works in computers, but I do not understand _why it's called that._ My general understanding of the method of complements is that e.g. a given number's nines' complement is whatever number gives you nine if added to the given number. If I apply that understanding to two's complement, then I would expect that for a given number, whatever number gives you two if added to the given number should be the two's complement. But that just doesn't seem to match what "two's complement" is in computers. For instance, in a computer's four-bit two's complement numbers, 1011 is -5, but where does that give you two? Basically, I don't understand the mathematical etymology of our computers' "two's complement" at all.
@@ropersonline This I am _far_ less confident about, since etymology, while interesting, is more about history and psychology than it is about math, which makes it so much more confusing and inconsistent. From what I can tell, it's a special case of "radix complement" (where "radix" is another word for "base") for specifically when the radix is 2. "b's complement" seems to be based on -x being b^n - x, but when doing modular arithmetic, that just becomes obvious since b^n ≡ 0 mod b^n, so -x = 0 - x ≡ b^n - x = (b^n - 1) - x + 1. That's just math, not language. Officially the math is called "modular arithmetic," but its name is exactly as arbitrary as "radix complement." Some people say that math is about giving the same name to different things, and while I do partly agree, I've come to believe that it's even more about giving different names to the same thing. "Radix complement" is just a way of shifting the labels for half of the congruence classes of a modular arithmetic to call them "negative," even though modular arithmetic itself has no concept of positive nor negative, nor any ordering at all. And that's not getting into the p-adic integers, which is another arbitrary name with no apparent connection to its meaning, which essentially describes idealized infinite digit strings with p's complement.
@@angeldude101 Honestly, much of your answer went clean over my head, and I still don't really understand the reason why. I guess I would need someone to put it in more simple terms. Just to ask this though: Does ≡ mean "is equivalent to"?
@@ropersonline Pretty much. Formally it's "congruent to." Two numbers are "congruent" with respect to a given "modulus" if both give the same (positive) remainder when divided by that modulus. When the modulus is a power of 2 like 2^n, then congruence means the two numbers share their n least significant bits. 256 and 0 are still considered different numbers, but they're indistinguishable with 8 bits because they're "congruent mod 2^8".
Thank you for teaching beginners how to think about numbers. I'm glad you're learning rust and getting into this! Just one note about why programmers don't use large numbers. It's not just for performance. Actually performance is the least of our worries. It's basically because it's pointless and can even introduce a security threat. First reality a new learner settles with is that math in programming isn't like math in real life. You'll never be able to have all the freedom you have when you do math on paper. Computers have limited memory, no matter how big they are. After having settled with that, let's start building things. When you build a program you build a "model" of something. Most of the time you don't need big numbers. Like when you push elements to a vector. That vector will never have a size larger than the max size of a 64 bit integer, because your memory will never be able to handle that even if you're using a super computer... why would you want to hold it in a 256 integer or 1000000 bit integer then? There's no point. Given that we settled that programming math is not like math on paper, you just ask yourself, what's the worst case scenario for a vector size? And you choose based on that. Finally, security is an important consideration. Think of your program as a huge state machine. The more states your program can be in, the more security tests you need. Understanding the full, complete and provably correct behavior of a function that uses 8 bit integers is much easier than one that uses 128 bit integers. It's much easier to make formal proofs that will grant you security guarantees. After all, programming is not about monkey typing code, believe it or not anyone can do that, it's about delivering software that does exactly what we expect it to do, which turned out to be a difficult problem. Smaller integers can make this task much easier when used wisely.
You should probably make a distinction between sign-magnitude notation and two's compliment. The image at 5:57 shows sign-magnitude notation, where the difference between a 7 and -7, for example, is just the left-most bit (so 7 = 0111 and -7 = 1111). Floating point numbers work that way, but signed integers use two's compliment, like you show at 6:54. The big difference being that the negative numbers run the other way, so 1111 is -1 instead of -7. The advantage of two's compliment is that you can simultaneously (a) interpret positive numbers the same as if they were unsigned (so 0111 = 7 in both the u4 chart at 1:05 and the i4 chart at 6:54) and (b) don't have to treat counting down past 0 as a special case (if we try to subtract 1 from 0000, the integer underflows, and we get 1111, which, in two's complement, is -1).
I have to say, you are really good at explaining. I struggle with abstract concepts often, but you provide clear examples that give context. I watch most of your stuff regardless, but more teaching video's like this would definitely be interesting!
I knew quite a bit about signed integers yet I never heard about the positive and negative number overflowing to 0 when added! That's really cool design!
Finally some non click bait you have no idea how cool it was to hear you bring up rs gold limits when I was just thinking of it when you described pacman
Bro I am in college I have an exam next week where one of the topics is signed and unsigned binary numbers. This video explains it perfectly. Love your videos
While I wish you hadn't even mentioned pointers here because of the way in which you brought them up, all the rest is absolutely spot on. Hopefully you'll do a video on pointers to fully explain them, and if you do, I'd recommend you delve into the different sized pointers from the DOS era as well as the change from 32-bit to 64-bit platforms.
I think it’s a shame that low level programming doesn’t get much limelight these days, at least in terms of what young people are starting out on. Machine learning may obsolete all the jobs anyway, at least in part, BUT being able to actually manipulate hardware directly is a far cry from the people I’ve spoken to that think making python scripts for web apps is worth student loan debt and a secure job. RIP Terry
I don't know a lot about coding, however i do believe that machine learning will not obsolete basic coding, at least not fully, imagine using code from an algoryrhm without checking it first, imagine the bugs and the chaos to the whole code that could create. Also i agree with your thought.
I don't have much interest in low level programming, it's more interesting for me to deal with high level stuff, databases, UI's, simple Python scripts, etc, but it's still cool to know about this stuff and I am interested in getting programs to run as fast as possible and learning about how NumPy does it, or crafty built in methods, etc.
As someone who is more interested in low level programming than higher level programming, I get a lot of weird reactions from people who are otherwise really into computer science. Stuff like "why would you bother doing this" or "isn't it confusing having to know and precisely define data types" etc. I'm at university and not even studying computer science because the courses available don't really interest me.
a good way to remember signed vs unsigned is seeing the word "sign" as "negative sign", which tells you whether the number is capable of being a negative number or not. -100 has a negative sign so it must be a signed integer.
For somebody who's not familiar with two's complement representation, 6:54 is not gonna make any sense. Previously (5:58) you were showing a simpler representation where the only difference between +N and -N is the first bit. But now suddenly negative numbers are completely different from their positive counterparts, for example one would assume that the negative of 0010 is 1010, but here it's actually 1110 without any explanation.
It's a hold over attitude from the 90s being taught by those old devs who are now instructors. in the 90s user expectations were still low and people bedazzled by any crude graphics; and computers really were following Moore's law so it was more cost effective to just upgrade hardware in a year than to optimize code. For common desktops, CPU single core speeds went up over 50x and RAM size 100x in 10 years; while CPU single core has gone up about 5x and ram size 30x in the last *20* years.
At 5:57 you show how it works for one's complement, but this is practically never used. The encoding scheme we use is two's complement, there the displayed number 10101101 would be -83, not -45. Your previous diagram showing them on a wheel works much better as an example.
Great vid explaining signed and unsigned binaries, great explanation on some stuff that I couldn't understand at times when programming with C or C++ at times
For us as well 😄 (Jena, Germany), but idk about filtering. There were lots of modules in the beginning to slowly filter them 😉. In physics, filtering was extreme 🙈. They started the first semester with lots of differential equation solving. 😨 (I passed with a 3 on first try though :))
@@AntonioNoack Yep, German aswell. Math and c reduced the number of students by a lot. Still have to take Differential equasions, but shouldnt be an issue with enough practise. But im glad they take in many and give them a chance to prove themselfes. I never had good grades in school, but im doing well in uni.
for the bitsize of number a more "modern" example to explain the size issue is the Arduino card with only 8ko of memory for a mega 2650 you need to choose carefully the correct integer you want ^^
Often integers of smaller bit width are purposely used to prevent buffer overflows: for example, if you have a 256 elements long buffer, you can use a 8-bit unsigned integer for indexing it. This also works as a circular buffer. If the buffer is 512 elements long, you can use a 16-bit integer and AND it with 0x1FF every time before using it, and so on.
You are right that it was a mistake in the context of the video, but for the sake of completeness, integer overflow/underflow vulnerabilities can and have been used to exploit a buffer overflow when the culprit variable is used to index a buffer.
I already knew all this but I just like the way you described it with real world examples of what happens and the consequences of not considering this :P
I'm not sure if I misinterpreted part of the example you made at 10:07 and 10:34, but just to make it clear: A pointer's size does not depend on its type information. When talking about the kind of raw pointers you use in C, then they just need to be big enough to cover the entire address space, since they just represent a memory address. The "type information" (whether it points to a signed 32 bit integer / an unsigned 8 bit integer / a double etc.) is only used during compilation time by the compiler to generate the final Assembly
@@theodis8134 Near and far had no connection to the type of data pointed at. Near and far only indicate the offset within a section and section of physical memory with direct physical addressing. Current x86 operating systems present applications with a virtual memory space. Though OS developers may still deal with some pseudo-physical addresses as presented by the memory management controller. Embedded devs still need to work with real physical memory but that is machine specific.
I see someone is working through the Rust by Example guide! ;) I'm trying to go through it, as I'm sure many others are as well, and this video was very informative! I'd love to see more videos as you progress through the Rust by Example guide where you explain the topics you learn. For you, it could help keep you on track and motivated to finish the guide, and we could receive videos with great explanations and examples of some of the concepts in the guide that are more difficult to understand!
I'm willing to bet most game programmers don't even have to deal with this. So many studios just use pre fabricated game engines now that they barely ever deal with engine level code. Modern developers are basically asset flippers. They take an engine that already exists and just load it with all their own assets. The game engine is what used to make game releases back in the late 90's so exciting. Because developers back then didn't have tool kits, they had to develop their own which lead to very rapid development of the engine software technology.
Usually correct these days yeah. A lot of game dev has shifted over to "light" programming if anything. Hell a lot just flat use node programming as well.
Love the explanation, already had a decent grasp of binary but the signed integer part was really neat. Also any video that features the latest OldSchool boss within a day of release without that being the focus is excellent.
Others have commented on how signed integers don't usually use a digit to represent a sign, and instead use "two's compliment". For a more visual explanation, a 4-bit unsigned int has an 8's place, 4's place, 2's place, and 1's place. But a signed 4-bit would have a _-8's place'_, 4's place, 2's place, and 1's place. Instead of having the first digit be a negative symbol, it's a negative, largest-place number. That feels weird, but it actually makes the math easier. For the signed integer I showed previously, if I have a one (0001) and subtract one, it will become zero (0000) and then if I subtract another one, it "underflows" to become "1111". Except look what the value is: -8 plus 4 plus 2 plus 1 = -1. So we can use the exact same addition/subtraction operation with both signed and unsigned integers without having to "check" if the value is positive or negative to start with. If the first digit was a the sign of the bit, and we had the number one (0001), if we subtract two manually, we have to change the sign once we go below zero. You still risk normal underflow (if you subtract from -8 (1000) then you get +7 (0111) or if you add to +7 you get -8, but the digits are kept in proper order. But all you have to do is keep in the normal range (-8 to +7) and you are fine. It's actually quite ingenious.
As always, another great video! Now you should make one showing noobs how to install a secure copy of runelite to a flash drive that can run undetected on a corporate PC.
Thanks for explaining the real-world consequences of lazy programming at the end, it really helps put a lens on why your computer is screaming at the top of its lungs when you run these games.
9:36 If you're serious about going fast, the main reason not to use 64 bit ints for everything is not RAM usage, but rather not fucking up your program's cache coherency. Reading memory in L1 cache is ~2 orders of magnitude faster than main ram (think 3 cycles vs 300), so there's a lot of value in not filling it up with garbage. On modern x86 CPUs, the program loads memory from RAM into cache 64 bytes at a time (that's the slow 300 cycles trip) - if everything is a u64 you can get at most 8 meaningful values from a single trip to main ram, but the more tightly your data is packed, the more value you can get from that single trip
With the caveat that many programmers don't know enough about structuring data to do this without making it even slower than when they started. int length is totally irrelevent if plopped onto the heap by some virtual class's vector of pointer indrection to actual data, or if the compiler has to zero pad all of the subtypes of a larger structure to get it aligned.
My favorites case of integer overflow in games has to be the nuclear Gandhi form Sid Meier's Civilization, it is till this day one of the funniest glitches of all time
If you want to learn more about computer systems on this low level, I highly recommend you all go and play turing complete on steam! It's taught me a lot of really cool stuff on how computers work. Fyi, the goal of the game is to make a 8-bit computer from scratch basically, which sounds hard, but it does an excellent job of walking you through it starting from making basic gates, all the way to writing your own flavor of assembly. Highly recommend!
Came here thinking this was talking on some sort of signed binary type. It sounds like it would be in base 3 with -1, 0, 1 for potential digits, dispite that being some cursed signed trionary type. I was curious on how the discrepancy could be explained. Then I zoned out till the end when I realized this was just going over basic binary interpretations of integers. At least we know the clickbait works! "Signed and unsigned number in binary" probably would've been a more accurate title.
I loved the way you explained it. Very clever and well illustrated. Thanks, Kenny! I hope to see more videos explaining concepts like this in the future.
Quick correction I haven't seen anybody mention yet: A pointer does not have the same size as the variable it points to. It just needs enough space to hold a memory address.
Just an small thing, bigger ints might sometimes be faster than smaller ints, depending on the cpu, you may check c++ fast_int stuff if don't believe me.
Yeah, it's been awhile since I've been school for this stuff, but I vaguely remember the most optimal sized integer for processing is based on the size of the data bus. Making it smaller can actually cause performance penalties since it's going to pull from memory in data bus sized chunks and then need to shift and mask the portions of the data it doesn't need. I think it's also why C will pad structs to be in multiples of the bus size.
@@theodis8134 CPU's have sub registers that can pull smaller sized chunks, well more specifically it will pull 64 bits but then there's a low/high 32 bit sub register you can call either of etc. The problem is when the data you want to get isn't properly aligned in memory to easy to access byte boundaries that align with the registers. This is why stuff is usually padded out to bus width sizes simply so that it aligns nicely in memory for fast reads.
The negative binary numbers are also represented by the complement of its positive number for example 7 = 0111 but -7 = 1001. This is known as the 2s complement of a binary number, which is the same as the 1s complement but you add 1 at the least significant bit. The 1 complement of 7 would be just flipping all 1 to 0s and all 0s to 1 and by 2s complement would be the exact same process just by adding +1 to the end. 🤓
What a coincidence, we're discussing number bases in class and soon we'll discuss signed integers. Very glad that you're interested in making educational videos as well!
there's another reason why programmers tend to use unsigned pointer sized integers for the size of something: it cannot be negative. Thus you don't have to check if the variable is less than zero. Plus the memory space has a size limit that depends on a data bus size. Nowdays it's mostly 64bits but some devices are still using 32bit buses. And it means, that a max possible address value is exactly the max possible value of an unsigned pointer sized integer.
Modern CPU are so RAM bottlenecked that you still have to write some code like you only have KB or a few MB so it will fit in cache. Even there it has to compete against the other 383 concurrent threads
In a nutshell: "Let's use 1 bit to allow for the representation of negative numbers" This limits maximums a bit per (uh, memory :| ) A bit that changes whether the number is positive or negative seems pretty significant.
it's actually not as simple as dedicating a bit for sign, computers use 2's complement instead which is better since it doesn't waste 2 representations for 0. for example, if we simply dedicated a bit for sign then: 1000 and 0000 will both equal 0, which is not great.
Very cool. So I assume when you are initializing an integer in a program where you care about optimization (ideally all of them lol) you have to triage by asking yourself how big an integer needs to be, and if there's a risk of over/underflow.
Generally for speed you want to use ints the size of the CPU architecture or at a half size. So on a 64 bit CPU use 64 bit or 32 bit ints, both are generally fine. There are probably some CPU's out there where going half size isn't fine but on X86 afaik its completely fine because there are sub registers. Going smaller than that can cause speed slowdowns. As for overflow/underflow, yes that's always something you need to consider when working with ints.
I mean about those 64bit integers, hustle is about that you can only load 64bit integers in current gen cpu architecture but e.g. if you use 32bit integers compiler might optimize it to the point it can even use 32bit registers (backwards compatible) so you almost get double performance on some operations if im not mistaken registers are considered L1
You can get double the performance only if using floating point math in SIMD units which have 128, 256, or 512bit packed registers. General purpose registers don't pack multiple numbers.
I find it crazy how when Pac-Man was being made that they didn’t check for integer overflows in the level counter. Would have been a single if statement at each level start
I have great respect for people that take any concept, simple or complex, and explain them in a way such that anyone can learn them
How can I make a successful investment in stocks and profitable trades?? I’m thinking of expert valerie yarvin 😏 and suggestions🤷
How can I get in touch with her I’m in need of her assistance
Пчелен мед
♱𝟭𝟱𝟭𝟴𝟯𝟭𝟬𝟴𝟱𝟴𝟰
Пчелен мед👍👎
That’s her Whatsappinfo chat her up she’s mostly active there
She’s earned my trust since last year October when I hit my 140k YTD monthly trading profit target.❤️
3:20 2.1 billion is for a SIGNED int. unsigned int goes to 4.2 billion
yup noticed that too
-2.1 and 2.1 = 4.2
@@D-K-C -2.1+2.1 = 0
5:58 correction, we don't use a sign bit to represent a number which would result in the existence of 0 and -0 (negative 0), for example 0000 and 1000 in int4, instead we use 2's complement numbers, where essentially we take the leftmost bit and flip it's sign, for example xyzw int4 would equal to 2^0*w + 2^1*z + 2^2*y - 2^3*x (attention to the minus in the equation)
Twos compliment also allows subtraction to be treated exactly like addition, so both can be on the same hardware. And getting the negative of a number is as simple as flipping all the bits and adding 1
@@puddleglum5610 not having a -0 is a bonus, the main benefit is, as you pointed, that you don't need dedicated checks and hardware to deal with negative numbers
Lol, op is such a nub
@@guiorgy 1s complement already does that tho right?
@@hwstar9416 No, 1s complement still has the issue that 0 and -0 exist. With one's complement we just invert bits, so 1 as an 8 bit integer is now 0000 0001, making -1 equal to 1111 1110 or the inverted number. This means both 0000 0000 and 1111 1111 are coded as zero.
Only with 2s complement is this no longer an issue. And it has the side effect that the MSB still exists, as soon as you reach a maximum value it flips your MSB., Take 8bit integers as an example, we go from 127 or 0111 1111 to -128 or 1000 0000. So the first bit still indicates negative numbers.
Integer sizes also play a major role in networking. Double your integer size and you will double your network usage, and consequent costs, both for transmission of said bytes, and processing/storage on your server. Especially relevant for MMOs.
Just a heads up on a slight inaccuracy: you described the “signed magnitude” representation of signed integers, but modern hardware doesn’t use this. It uses the “two’s compliment” representation. This representation allows for integer addition and subtraction to run on the same hardware, and makes it so taking the negative of a number is as simple as flipping all of the bits of the number and adding 1.
Either way, nice refresher on my CS101 course from a few years ago!
Two's compliment was the shit. This brought back memories from learning to code a Risc V processor in my Computer Science engineering degree.
he does at least go through and describe the actual representations in the examples, and in the documentation he flashes on the screen it mentions twos complement. but I 100% agree and I was thinking the same thing as soon as he mentioned it. I assume this video was meant to be "eli5" lie-to-children level stuff, in which case I think the explanation was acceptable, if a bit frustrating for someone with a cs background xD
@@alicecubensis1221 To be fair, I don't think Kenny has studied CS (correct me if I'm wrong) so it's kinda hard to expect that he knows of something like this or has ever had to physically draw a full adder. And also he mentioned that he is not a programmer so more power to him, having to remember things like IEEE 754 and little-endian or big O notation is stuff you can barely grasp in a CS degree already.
The actual examples he have provided with 4-bit integer are for two's complement, it's just the visual at 6:00 that shows signed magnitude.
Wait till you hear about Thirds' Complement.
This video on binary numbers and buffer overflow/underflow is an absolute gem! The explanations were clear and easy to follow, and the real-world applications highlighted throughout made the material relatable and understandable. It's a great resource for anyone looking to deepen their knowledge on the subject matter. Thanks for sharing.
Nonbinary numbers
Can a binary number now be declared as being non-binary?
unidentified number
'sup
Bases are fluid, and you shouldn't assume a number's base or force to conform to a base role
@@Zooiest you are a real Linux user
Dude every video you make has something cool and nerdy in it I love it. Thanks for contributing man.
I was installing Linux the other day and wound up on your vids.
I was learning how to a cook a dessert and wound up on your vids.
I was learning about security vulnerabilities and wound up on your vids.
You're like a a modern lightweight tech-Da Vinci. That's intended to be a compliment. :)
That's a good way to put it! Tech da vinci :D
lol that's an insult to Da Vinci
Your video games to make the subject much more approachable is a great idea. I will be showing this video to my students for sure. Keep up the great work.
>american education
@@coomer8265 ye in germany probably no teacher would do that.
mainly because the overhead projector is the pinacle of technology in german schools...
@@Buttersaemmel What, you guys have projectors in German schools?
What class do you teach Mr?
I'm new in the education team😎😂
I teach adult students. I'm not in the confines of a public education system. It's also a side gig I do to help out people trying to learn programming. My day job is low level networking engineering. I'm currently using rust to build extremely efficient custom networks for applications that have a high volume of traffic.
It's not true, that bigger integers are necessarily slower.
Often math on bigger integers is even faster than on smaller ones. The most efficient number is often the one corresponding to the architecture. If you're on a 32 bit system, 32 bit integers are often the fastest, if you're on a 64 bit system, 64 bit integers are often the fastest.
But what's more important than that is cache size and alignment. Using bigger numbers might be bad for the cache, using different sizes of integers depending on the use case might be bad for the alignment. The latter is normally optimized by the compiler, so there is empty space between integers, so you don't have the smaller size for using smaller integer sizes for some values, while still using having the overhead of doing math with smaller integer sizes.
Yeah this is a good point. Unless the size of your integer is important (for example if you're working closely with memory or drivers) you should just use a plain old int or unsigned
@@salsamancer usize is the default in rust.
I don't want to be "that guy" porky, but actually a lot of what we used to be taught about CPU arcitecture (cost of a cache miss, speed of L1/2/3 memory, etc) is no longer true. The CPU holds so much fast cache memory, and the look-ahead branch predictors are so busy all the time, that things like cache alignment are no longer important considerations. Yes you can definitely write a program in C that does the bit packing with padding and alignment just right, but it might actually end up slower because the CPU can't figure out what you're trying to do and wasn't going to do what you asked specifically how you asked for it anyway. Modern computers actually suck TBH.
@@cannaroe1213 Sounds more like an extention of the sloppy 90s attitude that next year's hardware will cover up this year's poor software design.
It is true that blind attempts at optimization, by some jr. dev that copy pasta'd their way through school with a teacher from 1985, can often result in hindering both the compiler and machine. However branch prediction, look-ahead prefetching, and large cache are still not magic and simply are forbidden from certain optimizations that might change fundamental parts of the code. eg. The programer may know the variable will never need to be outside of 0-255, but the machine cannot assume this and so cannot reduce a long to a short regardless of the optimizing algorithm or architecture.
Nobody here is talking about bitpacking which is a somewhat different concept to alignment of primatives.
Maybe some interactive program like a game can be a bit sloppy with relatively large caches; but many backend processes are still dealing with orders of magnitude more data than can be handled by even the largest current gen caches. Vectormath SIMD units are also a thing.
(Signed vs unsigned is a bit more complicated, on one hand it is a good way for the compiler to find certain problems and to lock in certain behaviors and parameter requirments without separate validations. On the other hand certain CPUs may be faster with one or the other type of math, but that is a very specific super-tune and should be based on profiling, it would take a heap of int math per second for that difference to be relevent.)
3:24 Should it be *signed*, rather than unsigned? An unsigned 32-bit integer should be able to go up to 4.2bill instead of only 2.1bill, if I'm not mistaken.
Yep! And OSRS is written in java so they don't have access to unsigned types.
Literally why was it so hard for my bootcamp instructors to explain this? You're doing an incredible thing with the way you explain stuff, dude.
Because they are unqualified hacks in a what is basically a pyramid scheme.
Love the way you explained this stuff, I remember back in uni not everyone could wrap their heads around why this was even a thing.
This channel is by far much better than the classes I got in university
It's not a sign bit, it's two's complement. The leftmost bit gets it's magnitude flipped so for example instead of 128 it's -128, so a value of 1000 0000 is -128 (which is why a signed int8 with value 127 will overflow)
This is a solid video, but also a bit of a missed opportunity to explain more about two's complement and the alternatives, and why two's complement is better. In part two, maybe?
The alternatives are signed magnitude, which holds the absolute value in the lower bits, and sets the highest bit if it's negative, and 1's complement, which flips all the bit of the absolute value when the number is negative. 2's complement is a result of observing that the greatest unsigned value plus 1 gives 0 and simply filling things out from there. If 15 + 1 ≡ 0 when ignoring overflow, then logically 15 ≡ -1, which carries over to 14 ≡ -2, 13 ≡ -3, etc. For ease of implementation, the values with the most significant bit set are treated as negative (more specifically, their unsigned interpretation minus 2^n where n is the number of bits), even if this means that --8 ≡ -8.
It's better because it's derived from the existing behavior, allowing negative numbers to be treated the same as positive or unsigned numbers in most cases. 1's complement and signed magnitude require special casing addition and subtraction depending on the numbers' signs and relative magnitudes. (Though multiplication is relatively easy for all three, though slightly more complex for 1's complement. Division is annoying for all of them, though truncating division (rounding to 0), which most computers use, is _slightly_ easier with signed-magnitude, though it's also not what many programmers or mathematicians actually want.)
@@angeldude101 Thank you. Could you also explain _why_ the two's complement method of implementing signed numbers in computers is _called_ two's complement? I do sort of understand _how_ the so-called "two's complement" system works in computers, but I do not understand _why it's called that._ My general understanding of the method of complements is that e.g. a given number's nines' complement is whatever number gives you nine if added to the given number. If I apply that understanding to two's complement, then I would expect that for a given number, whatever number gives you two if added to the given number should be the two's complement. But that just doesn't seem to match what "two's complement" is in computers. For instance, in a computer's four-bit two's complement numbers, 1011 is -5, but where does that give you two? Basically, I don't understand the mathematical etymology of our computers' "two's complement" at all.
@@ropersonline This I am _far_ less confident about, since etymology, while interesting, is more about history and psychology than it is about math, which makes it so much more confusing and inconsistent. From what I can tell, it's a special case of "radix complement" (where "radix" is another word for "base") for specifically when the radix is 2. "b's complement" seems to be based on -x being b^n - x, but when doing modular arithmetic, that just becomes obvious since b^n ≡ 0 mod b^n, so -x = 0 - x ≡ b^n - x = (b^n - 1) - x + 1. That's just math, not language. Officially the math is called "modular arithmetic," but its name is exactly as arbitrary as "radix complement."
Some people say that math is about giving the same name to different things, and while I do partly agree, I've come to believe that it's even more about giving different names to the same thing. "Radix complement" is just a way of shifting the labels for half of the congruence classes of a modular arithmetic to call them "negative," even though modular arithmetic itself has no concept of positive nor negative, nor any ordering at all. And that's not getting into the p-adic integers, which is another arbitrary name with no apparent connection to its meaning, which essentially describes idealized infinite digit strings with p's complement.
@@angeldude101 Honestly, much of your answer went clean over my head, and I still don't really understand the reason why. I guess I would need someone to put it in more simple terms. Just to ask this though: Does ≡ mean "is equivalent to"?
@@ropersonline Pretty much. Formally it's "congruent to." Two numbers are "congruent" with respect to a given "modulus" if both give the same (positive) remainder when divided by that modulus. When the modulus is a power of 2 like 2^n, then congruence means the two numbers share their n least significant bits.
256 and 0 are still considered different numbers, but they're indistinguishable with 8 bits because they're "congruent mod 2^8".
Thank you for teaching beginners how to think about numbers. I'm glad you're learning rust and getting into this!
Just one note about why programmers don't use large numbers. It's not just for performance. Actually performance is the least of our worries. It's basically because it's pointless and can even introduce a security threat.
First reality a new learner settles with is that math in programming isn't like math in real life. You'll never be able to have all the freedom you have when you do math on paper. Computers have limited memory, no matter how big they are.
After having settled with that, let's start building things.
When you build a program you build a "model" of something. Most of the time you don't need big numbers. Like when you push elements to a vector. That vector will never have a size larger than the max size of a 64 bit integer, because your memory will never be able to handle that even if you're using a super computer... why would you want to hold it in a 256 integer or 1000000 bit integer then? There's no point. Given that we settled that programming math is not like math on paper, you just ask yourself, what's the worst case scenario for a vector size? And you choose based on that.
Finally, security is an important consideration. Think of your program as a huge state machine. The more states your program can be in, the more security tests you need. Understanding the full, complete and provably correct behavior of a function that uses 8 bit integers is much easier than one that uses 128 bit integers. It's much easier to make formal proofs that will grant you security guarantees. After all, programming is not about monkey typing code, believe it or not anyone can do that, it's about delivering software that does exactly what we expect it to do, which turned out to be a difficult problem. Smaller integers can make this task much easier when used wisely.
IPv6 should have gone down to 16-bit instead of 128
Mental outlaw teaching me is crazy, I love it! dude's great at this stuff, we need more of it!
I always prioritize your Linux videos over other's, but comp sci by you would be gold for me.
why? he's clearly not that knowledgeable about it
Why do you prioritize a overrated OS?
You should probably make a distinction between sign-magnitude notation and two's compliment. The image at 5:57 shows sign-magnitude notation, where the difference between a 7 and -7, for example, is just the left-most bit (so 7 = 0111 and -7 = 1111).
Floating point numbers work that way, but signed integers use two's compliment, like you show at 6:54. The big difference being that the negative numbers run the other way, so 1111 is -1 instead of -7.
The advantage of two's compliment is that you can simultaneously (a) interpret positive numbers the same as if they were unsigned (so 0111 = 7 in both the u4 chart at 1:05 and the i4 chart at 6:54) and (b) don't have to treat counting down past 0 as a special case (if we try to subtract 1 from 0000, the integer underflows, and we get 1111, which, in two's complement, is -1).
Thanks that was bothering me.
Damn, I didn't even notice XD
Better than my university lectures. They would probably play this at university for an online course.
I have to say, you are really good at explaining. I struggle with abstract concepts often, but you provide clear examples that give context. I watch most of your stuff regardless, but more teaching video's like this would definitely be interesting!
Well i didn't knew how much I needed to know what singed and unsigned integers are. Thank you
I knew quite a bit about signed integers yet I never heard about the positive and negative number overflowing to 0 when added! That's really cool design!
Finally some non click bait
you have no idea how cool it was to hear you bring up rs gold limits when I was just thinking of it when you described pacman
Bro I am in college I have an exam next week where one of the topics is signed and unsigned binary numbers. This video explains it perfectly. Love your videos
While I wish you hadn't even mentioned pointers here because of the way in which you brought them up, all the rest is absolutely spot on. Hopefully you'll do a video on pointers to fully explain them, and if you do, I'd recommend you delve into the different sized pointers from the DOS era as well as the change from 32-bit to 64-bit platforms.
I think it’s a shame that low level programming doesn’t get much limelight these days, at least in terms of what young people are starting out on.
Machine learning may obsolete all the jobs anyway, at least in part, BUT being able to actually manipulate hardware directly is a far cry from the people I’ve spoken to that think making python scripts for web apps is worth student loan debt and a secure job.
RIP Terry
I don't know a lot about coding, however i do believe that machine learning will not obsolete basic coding, at least not fully, imagine using code from an algoryrhm without checking it first, imagine the bugs and the chaos to the whole code that could create.
Also i agree with your thought.
I don't have much interest in low level programming, it's more interesting for me to deal with high level stuff, databases, UI's, simple Python scripts, etc, but it's still cool to know about this stuff and I am interested in getting programs to run as fast as possible and learning about how NumPy does it, or crafty built in methods, etc.
RIP
Go into FPGAs
As someone who is more interested in low level programming than higher level programming, I get a lot of weird reactions from people who are otherwise really into computer science. Stuff like "why would you bother doing this" or "isn't it confusing having to know and precisely define data types" etc. I'm at university and not even studying computer science because the courses available don't really interest me.
a good way to remember signed vs unsigned is seeing the word "sign" as "negative sign", which tells you whether the number is capable of being a negative number or not.
-100 has a negative sign so it must be a signed integer.
For somebody who's not familiar with two's complement representation, 6:54 is not gonna make any sense. Previously (5:58) you were showing a simpler representation where the only difference between +N and -N is the first bit. But now suddenly negative numbers are completely different from their positive counterparts, for example one would assume that the negative of 0010 is 1010, but here it's actually 1110 without any explanation.
9:10 the annoying part is that now people rely more on peoples hardware being top of the line, instead of writing good performant code.
It's a hold over attitude from the 90s being taught by those old devs who are now instructors. in the 90s user expectations were still low and people bedazzled by any crude graphics; and computers really were following Moore's law so it was more cost effective to just upgrade hardware in a year than to optimize code.
For common desktops, CPU single core speeds went up over 50x and RAM size 100x in 10 years; while CPU single core has gone up about 5x and ram size 30x in the last *20* years.
At 5:57 you show how it works for one's complement, but this is practically never used. The encoding scheme we use is two's complement, there the displayed number 10101101 would be -83, not -45.
Your previous diagram showing them on a wheel works much better as an example.
Nice to see runescape featuring....btw if anyone wants to double their GP just meet me at the grand exchange...
can trim my rune pl8, pls
Buying GF
Great vid explaining signed and unsigned binaries, great explanation on some stuff that I couldn't understand at times when programming with C or C++ at times
My uni started us of C. They did it to filter out all the people that lacked motivation.
For us as well 😄 (Jena, Germany), but idk about filtering. There were lots of modules in the beginning to slowly filter them 😉.
In physics, filtering was extreme 🙈. They started the first semester with lots of differential equation solving. 😨 (I passed with a 3 on first try though :))
@@AntonioNoack Yep, German aswell. Math and c reduced the number of students by a lot. Still have to take Differential equasions, but shouldnt be an issue with enough practise.
But im glad they take in many and give them a chance to prove themselfes. I never had good grades in school, but im doing well in uni.
for the bitsize of number a more "modern" example to explain the size issue is the Arduino card
with only 8ko of memory for a mega 2650 you need to choose carefully the correct integer you want ^^
Being able to count from 0 to 31 on one hand is a pretty cool party trick.
Often integers of smaller bit width are purposely used to prevent buffer overflows: for example, if you have a 256 elements long buffer, you can use a 8-bit unsigned integer for indexing it. This also works as a circular buffer. If the buffer is 512 elements long, you can use a 16-bit integer and AND it with 0x1FF every time before using it, and so on.
I didnt know of this use, interesting
It is integer overflow, not buffer overflow, these are different. Buffer overflow is something very different.
You are right that it was a mistake in the context of the video, but for the sake of completeness, integer overflow/underflow vulnerabilities can and have been used to exploit a buffer overflow when the culprit variable is used to index a buffer.
@@sywker True
That example about the game was super helpful
I already knew all this but I just like the way you described it with real world examples of what happens and the consequences of not considering this :P
I'm not sure if I misinterpreted part of the example you made at 10:07 and 10:34, but just to make it clear: A pointer's size does not depend on its type information. When talking about the kind of raw pointers you use in C, then they just need to be big enough to cover the entire address space, since they just represent a memory address. The "type information" (whether it points to a signed 32 bit integer / an unsigned 8 bit integer / a double etc.) is only used during compilation time by the compiler to generate the final Assembly
For modern C anyway. There used to be near and far pointers. It's something you could run across if you're stuck looking at really old code.
@@theodis8134 Near and far had no connection to the type of data pointed at. Near and far only indicate the offset within a section and section of physical memory with direct physical addressing.
Current x86 operating systems present applications with a virtual memory space. Though OS developers may still deal with some pseudo-physical addresses as presented by the memory management controller. Embedded devs still need to work with real physical memory but that is machine specific.
This is Waaay better than what I learnt in school
This goes to my list of videos to put to students if I go back to teach robotics/programming some day.
I see someone is working through the Rust by Example guide! ;)
I'm trying to go through it, as I'm sure many others are as well, and this video was very informative! I'd love to see more videos as you progress through the Rust by Example guide where you explain the topics you learn. For you, it could help keep you on track and motivated to finish the guide, and we could receive videos with great explanations and examples of some of the concepts in the guide that are more difficult to understand!
I'm willing to bet most game programmers don't even have to deal with this. So many studios just use pre fabricated game engines now that they barely ever deal with engine level code. Modern developers are basically asset flippers. They take an engine that already exists and just load it with all their own assets.
The game engine is what used to make game releases back in the late 90's so exciting. Because developers back then didn't have tool kits, they had to develop their own which lead to very rapid development of the engine software technology.
Usually correct these days yeah. A lot of game dev has shifted over to "light" programming if anything. Hell a lot just flat use node programming as well.
Now I finally understand ist, coupdnt get my head around it in grade 8 back in the day
Love the explanation, already had a decent grasp of binary but the signed integer part was really neat. Also any video that features the latest OldSchool boss within a day of release without that being the focus is excellent.
ngl i was hoping for another cooking video but everything you throw at us is interesting
Glad to to see yer motivated in the Rust journey 🌿
Others have commented on how signed integers don't usually use a digit to represent a sign, and instead use "two's compliment". For a more visual explanation, a 4-bit unsigned int has an 8's place, 4's place, 2's place, and 1's place. But a signed 4-bit would have a _-8's place'_, 4's place, 2's place, and 1's place. Instead of having the first digit be a negative symbol, it's a negative, largest-place number. That feels weird, but it actually makes the math easier. For the signed integer I showed previously, if I have a one (0001) and subtract one, it will become zero (0000) and then if I subtract another one, it "underflows" to become "1111". Except look what the value is: -8 plus 4 plus 2 plus 1 = -1. So we can use the exact same addition/subtraction operation with both signed and unsigned integers without having to "check" if the value is positive or negative to start with. If the first digit was a the sign of the bit, and we had the number one (0001), if we subtract two manually, we have to change the sign once we go below zero. You still risk normal underflow (if you subtract from -8 (1000) then you get +7 (0111) or if you add to +7 you get -8, but the digits are kept in proper order. But all you have to do is keep in the normal range (-8 to +7) and you are fine. It's actually quite ingenious.
As always, another great video! Now you should make one showing noobs how to install a secure copy of runelite to a flash drive that can run undetected on a corporate PC.
Thanks for explaining the real-world consequences of lazy programming at the end, it really helps put a lens on why your computer is screaming at the top of its lungs when you run these games.
Big ints for everything would cause trouble even on modern hardware due to the CPU cache suddenly having less stuff pre-poaded for calculation
9:36 If you're serious about going fast, the main reason not to use 64 bit ints for everything is not RAM usage, but rather not fucking up your program's cache coherency.
Reading memory in L1 cache is ~2 orders of magnitude faster than main ram (think 3 cycles vs 300), so there's a lot of value in not filling it up with garbage.
On modern x86 CPUs, the program loads memory from RAM into cache 64 bytes at a time (that's the slow 300 cycles trip) - if everything is a u64 you can get at most 8 meaningful values from a single trip to main ram, but the more tightly your data is packed, the more value you can get from that single trip
With the caveat that many programmers don't know enough about structuring data to do this without making it even slower than when they started.
int length is totally irrelevent if plopped onto the heap by some virtual class's vector of pointer indrection to actual data, or if the compiler has to zero pad all of the subtypes of a larger structure to get it aligned.
Thank you for the video. Nice change of pace
This feels like a blessing. Do comp sci videos outlaw. Help me pass my exams
Wow this is like insanely helpful, I’ve learned so much thank u cuh
Thank you for validating my education
My favorites case of integer overflow in games has to be the nuclear Gandhi form Sid Meier's Civilization, it is till this day one of the funniest glitches of all time
very cool, this is why i want to study a systems engineering carrer to learn and understand low level programing
Good video, thank you for great educational content as always
Super cool video Kenny. would love to see more vids like this
If you want to learn more about computer systems on this low level, I highly recommend you all go and play turing complete on steam! It's taught me a lot of really cool stuff on how computers work.
Fyi, the goal of the game is to make a 8-bit computer from scratch basically, which sounds hard, but it does an excellent job of walking you through it starting from making basic gates, all the way to writing your own flavor of assembly. Highly recommend!
Thanks for the cool video, love little tech bits like this
Dope video as always even tho I use this every day haha. Maybe a video about 1 and 2 complement representation and float would be nice as well.
real good intro to topic. thanks for video
Thank you, I love those videos. I learn a lot from you
Once you start working with Floats, everything math-related becomes total spaghetti
Came here thinking this was talking on some sort of signed binary type. It sounds like it would be in base 3 with -1, 0, 1 for potential digits, dispite that being some cursed signed trionary type. I was curious on how the discrepancy could be explained. Then I zoned out till the end when I realized this was just going over basic binary interpretations of integers. At least we know the clickbait works!
"Signed and unsigned number in binary" probably would've been a more accurate title.
Going back to basics huh, nice (hope it's a series though, we do all kind of know this)
man, i like seeing you making that kind of videos 👍 hoping to see more...
Love to your country from Russia
This guy got so much wrong
I loved the way you explained it. Very clever and well illustrated. Thanks, Kenny!
I hope to see more videos explaining concepts like this in the future.
Don't confuse "buffer overflow" with "integer overflow"
I love this content, how is learning rust going Kenny?
Quick correction I haven't seen anybody mention yet: A pointer does not have the same size as the variable it points to. It just needs enough space to hold a memory address.
Pointer may have the same size. x86_64 architecture with 64 bit integers for example.
What socks do you wear for programming, Kenny?
Protection
the GMP nightmares are coming back
Man, your content is gold.
Just an small thing, bigger ints might sometimes be faster than smaller ints, depending on the cpu, you may check c++ fast_int stuff if don't believe me.
Yeah, it's been awhile since I've been school for this stuff, but I vaguely remember the most optimal sized integer for processing is based on the size of the data bus. Making it smaller can actually cause performance penalties since it's going to pull from memory in data bus sized chunks and then need to shift and mask the portions of the data it doesn't need. I think it's also why C will pad structs to be in multiples of the bus size.
@@theodis8134 CPU's have sub registers that can pull smaller sized chunks, well more specifically it will pull 64 bits but then there's a low/high 32 bit sub register you can call either of etc. The problem is when the data you want to get isn't properly aligned in memory to easy to access byte boundaries that align with the registers.
This is why stuff is usually padded out to bus width sizes simply so that it aligns nicely in memory for fast reads.
@3:24 *signed integer; unsigned would go to ~4B.
The negative binary numbers are also represented by the complement of its positive number for example 7 = 0111 but -7 = 1001. This is known as the 2s complement of a binary number, which is the same as the 1s complement but you add 1 at the least significant bit. The 1 complement of 7 would be just flipping all 1 to 0s and all 0s to 1 and by 2s complement would be the exact same process just by adding +1 to the end. 🤓
What a coincidence, we're discussing number bases in class and soon we'll discuss signed integers. Very glad that you're interested in making educational videos as well!
I can see you are really becoming a Rustacean!
Thank you for videos you like this PLEASE DO MORE, for similar topics it helps alot
You didn't understand shit he said, don't act like you did.
@Alastor I am a cs student with more projects then numbers you can count to, considering you got the iq of a myopic sewer rat
there's another reason why programmers tend to use unsigned pointer sized integers for the size of something: it cannot be negative. Thus you don't have to check if the variable is less than zero. Plus the memory space has a size limit that depends on a data bus size. Nowdays it's mostly 64bits but some devices are still using 32bit buses. And it means, that a max possible address value is exactly the max possible value of an unsigned pointer sized integer.
I didn’t quite understand this, I’ll have to look into it a ’bit’ more
Modern CPU are so RAM bottlenecked that you still have to write some code like you only have KB or a few MB so it will fit in cache. Even there it has to compete against the other 383 concurrent threads
Once again, thank you sir
In a nutshell: "Let's use 1 bit to allow for the representation of negative numbers"
This limits maximums a bit per (uh, memory :| )
A bit that changes whether the number is positive or negative seems pretty significant.
it's actually not as simple as dedicating a bit for sign, computers use 2's complement instead which is better since it doesn't waste 2 representations for 0.
for example, if we simply dedicated a bit for sign then:
1000
and
0000
will both equal 0, which is not great.
@@hwstar9416 schuduppa yoh face uhh! r/Whooosh
Very cool. So I assume when you are initializing an integer in a program where you care about optimization (ideally all of them lol) you have to triage by asking yourself how big an integer needs to be, and if there's a risk of over/underflow.
Generally for speed you want to use ints the size of the CPU architecture or at a half size. So on a 64 bit CPU use 64 bit or 32 bit ints, both are generally fine. There are probably some CPU's out there where going half size isn't fine but on X86 afaik its completely fine because there are sub registers. Going smaller than that can cause speed slowdowns.
As for overflow/underflow, yes that's always something you need to consider when working with ints.
Hey! I see you started your rust journey. How is it going so far? Great explanation by the way!
I mean about those 64bit integers, hustle is about that you can only load 64bit integers in current gen cpu architecture but e.g. if you use 32bit integers compiler might optimize it to the point it can even use 32bit registers (backwards compatible) so you almost get double performance on some operations if im not mistaken registers are considered L1
"if im not mistaken registers are considered L1". No, registers are considered L0 :).
L1 is extra hardware :).
You can get double the performance only if using floating point math in SIMD units which have 128, 256, or 512bit packed registers. General purpose registers don't pack multiple numbers.
This is actually useful for me as I'm learning digital circuits
Tricked into learning CS!
I find it crazy how when Pac-Man was being made that they didn’t check for integer overflows in the level counter. Would have been a single if statement at each level start
This comment is for the algorithm. Thanks for the nerd info
There are 10 kinds of people, those who understand binary, and those who don't.
Me: studying my CS Master degree abroad
Also me: watches this video lmao
Love these educational videos