In this lecture, we'll write a C program to calculate the floor and ceiling of a number. Before we can do that, we need to know what floor and ceiling mean. So floor is the largest integer that is not greater than x, the number we're trying to calculate the floor for. Ceiling is the smallest integer that's not less than x. So you can think of it this way, you can think of floor as the integer that's closest on the bottom of this number without going above it, and you can think of ceiling as the integer that's closest on the top of this number without going below it, and that's why they're called floor and ceiling. So the problem that we're going to solve in this lecture, is we're going to write a C program that takes some x as user input, and calculates the floor and ceiling for that number. The constraint that we're going to use in our solution is we're only going to do this for positive numbers, and we'll talk about why we do that as we implement our solution. So, let's go implement our solution. Here's our standards template file with a few extra comments. We're calculating floor and ceiling, and we're only going to work for positive numbers at least for our initial implementation of floor and ceiling. I have some comments for what we're going to do. We'll do a little extra, but that's good enough to start with. So the first thing we're going to need is we're going to need to declare a variable that will hold the x that the user enters. So I'm going to make this float because it's the floating point data type, and I'll call it x. Next, we need to prompt for and get a float from the user. So to prompt for, we use printf, and we'll say, "Enter floating-point number:" The next thing we need to do is, we need to read in the user input so that we can store that in the variable x. The way we're going to do that, reading in from the keyboard is we'll use scanf_s, and the underscore s means safe. So this is safer than scanf particularly when we're dealing with characters and strings. So we're going to just use scanf_s throughout this course. We're actually not going to use scanf_s throughout the rest of the course. We're going to use scanf. So it's true that scanf_s is safer than scanf, but the issue is that function is only available in Visual Studio. So if you try to use scanf_s in Xcode, you can't because that compiler doesn't have that function. This is actually one of the idiosyncrasies of programming in C. Different compiler vendors decides to implement a subset of C rather than all of C, or add extra stuff to the language that isn't in the standard, or a little bit of both. So we're going to try to stick with C standard code that is supported by both Visual Studio and Xcode. So I am going to need to add a pound define at the top of my code to make visual studio compile using scanf, but that's what we're going to do so that we're the standard C mechanism for getting input from the user. We provide to arguments. We provide a format specifier, and this is percent f just like when we're print effing afloat, and then we provide the address of the variable that we're reading into. So this address of operator may look strange to you, and that's because we haven't talked about pointers, and we won't even talk about pointers until the very end of the course. But periodically, we're going to have to talk about not the variable name itself, but where that variable actually lives in memory. This is one of those cases. So really at this point, all you need to know without a deeper understanding of how everything's working is that for scanf_s, we're providing the address of the variable we want to put the result into. So let's go ahead and control F5, and see how this all works, and there we go. So now, let's calculate and print floor. I know I'm actually going to want a blank line before I do that printf in the as always we'll label our output, and our floor is going to be an integer. So we'll use the %d format specifier, and here's where we can actually take advantage of the way C works when we do a type cast. So we know x is a floating-point number. But we can't do this because if we just print out the floating-point number especially using the %d format specifier, that's not going to be correct. What we want to do, is we want to typecast this to an int. So we've seen typecasting before, right? Where we type cast an int to a float to make floating-point division work properly. In this case, we're going the other way, where typecasting a float to an int, and when we do that, C does something called truncation. It just throws away the decimal part of the number, and that's exactly what we want here because we want the highest integer that's not above the number. So if we just throw away the decimal part that's going to automatically give us the floor. So if I do 1.3, floor is one just as we expected. Let's do ceiling next. You might think that we can just do this x plus 1 because then we'll jump x up one, and then we'll take the floor because typecasting to an int truncate and we should be all set, and you're filled with the foolish optimism. So we run it, and we say 1.3, and we're very excited because it seems to be working just right, and then I crush your hopes and dreams, and I say, "Well, what about one?" Because the answer for floor should be one, and the answer for ceilings should be one, and we get it wrong, because we've added one to one to make it two, 1 plus 1 is 2, awesome. When we typecast two to an integer, it stays at two. So our ceiling is incorrect. Now, here's what we could do. We could say, add slightly less than one. If I run it again, we'll test 1.3 to make sure that works and it still does. We'll test one again, ended that now works. That's great. However, 1.001 doesn't work because ceiling of 1.001 should be two. So we've added a limitation to our code here. I said it only works for positive numbers, and we should also say only works to two decimal places. It's important for us to include in our comments, what the limitations are on what we've written. We're actually going to fix both of these limitations in just a moment. But for what we've done so far, these are correct limitations. So we've calculated floor and ceiling here, and we've done it only for positive numbers and only to do decimal places. But it feels like, floor and ceiling are pretty standard things in math, and it seems like somebody should have already implemented this functionality for us. When you ever think that that might be true, the best thing to do is to go look at the documentation for the C standard library to find out. So let's go do that now. I have searched on and gone to the C standard library documentation. This one happens to be the Wikipedia page, and so, every C programming environment will include the standard library, the C Standard Library. It includes lots of those chunks of code we've talked about that we can pound and include, all contained in a header file. Well, the specification of what's in there is contained in the header file. That's what dot h files are. They're called header files. So if we were looking for a math function, we should go look at the C standard library documentation, click on "Math.h". That in fact, gives us a list of the functions that are provided in math.h. If you scroll around for a while, you will see that there are some nearest integer floating point operations, which is precisely what we need. Let's click on "Floor" because that gives us a little more information because there's actually three functions defined for getting floor within math.h. We have floorf, which takes a float as an argument and returns a float. We have floor, which takes a double and returns a double. We have floorl, which takes a long double, and returns a long double. So we really ought to use floorf because we're trying to get a floor for a float. The big message here is that, when you're getting ready to go implement a function for a variety of different things but it seems like wow this seems pretty common. It ought to be somewhere. You should definitely check the C standard library to see if it is available, and you can just pound include some code that somebody else wrote in the C standard library, and then you don't have to write it on your own. So we can calculate and print floor and ceiling using math.h. Now remember, if we need to use something from the C standard library, we have to come here to the top of our program and pound include what we're using. We're going to pound include math.h. That way, we can access the functions that are in math.h. Back down here, we'll printf. Then we'll say, "Floor using math.h." We're still going to print an integer. So we'll have to still typecast what we get from math.h floorf because floorf returns a float to us, and will provide x. So let's make sure this works. We'll just do it for 1.3. We'll test everything before we're all done. So there you go. It's getting the correct floor. I'm going to add another blank line, just so our output looks nicer. Now I'm going to copy and paste. We're going to do ceiling. Of course, I don't want to use floorf. I happen to know this is ceilf, ceil for ceiling. But of course, you could read the documentation to find out the correct function name for getting the ceiling. So now I'll control F5 and let's try all our numbers, 1.3, great. We'll make sure one works. Awesome. We'll try 1.001. Remember, ours doesn't work properly because we only do it for two decimal places. But, the ceiling function in math.h of course does it properly. So that's good. We've removed the two decimal place limitation, and now, let's do a negative number. Let's do negative 1.3. Our code where we're truncating by typecasting to int doesn't work at all as you can see. But, the math.h functions do. So remembering the definition of floor, floor is the greatest integer that's not above our floating point number. So when our number is negative, that means that it's further away from zero in negative. So floor is negative two, because that is the greatest number that's not greater than negative 1.3, and of course, ceiling is correct as well. So if we use math.h, everything works fine without our positive number only limitation and our two decimal place limitation. So I'll say this again when I recap. But, you should just use the functions that are available in the C standard library when possible. To recap, in this lecture, we developed a C program that calculates floor and ceiling for a user provided number. We started off by taking advantage of the truncation we get when we typecast to an int, with some limitations that we could overcome, once we knew some more C programming. We learned an important lesson though, and the important lesson was, we should check the C standard library to see if one of the packages provides the function we need to calculate, and it turns out that the math package does in this case. When in doubt, you should use the functions that are provided in the standard library, rather than implementing your own. We implemented our own, so that we could get some more practice with C programming and understand more about how typecasting works. But really, if the function's available in the standard library, use it.