ccs50

cs50 filter-more grayscale expected "20 20 20\n50 5...", not "20 20 20\n50 5..."


I am doing the cs50 course and I am in week 4 (Memory) and I am doing the homework.

this is my code for grayscale:

void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            uint8_t Red = image[i][j].rgbtRed;
            uint8_t Green = image[i][j].rgbtGreen;
            uint8_t Blue = image[i][j].rgbtBlue;
            uint8_t avg = (Red + Green + Blue) / 3;

            image[i][j].rgbtRed = avg;
            image[i][j].rgbtGreen = avg;
            image[i][j].rgbtBlue = avg;
        }
    }
    return;
}

Here are the results enter image description here

Can you explain the 27 not 28 and most importantly this: expected "20 20 20\n50 5...", not "20 20 20\n50 5..."


Solution

  • If you for example have the channel values 5, 4, and 8, then the sum of these values is 17 and the average is 5.666667.

    However, in C, when you write ( 5 + 4 + 8 ) / 3, then this is equivalent to 17 / 3 and will perform an integer division (Euclidean division), which means the result of the division is 5 with a remainder of 2. Therefore, the expression 17 / 3 will evaluate to 5 and the expression 17 % 3 will evaluate to 2 (which is the remainder).

    An integer division (euclidean division) is not the kind of division that you need for this assignment. Rather, the assignment wants you to perform a division with a fractional part, so the result is 5.666667, and then this result should be rounded to the nearest integer. Therefore, the result should be 6 in this example.

    In C, if both arguments of the / operator are of an integer type, then an integer division is performed. If at least one of the arguments is of a floating-point type (such as float or double), then the other argument is converted to the floating-point type and a floating-point division is performed instead of an integer division, so that the result is a floating-point value with a fractional part.

    Therefore, the easiest way to enforce a floating-point division is to change one of the arguments to a floating-point type. This can be done by changing the line

    uint8_t avg = (Red + Green + Blue) / 3;
    

    to:

    uint8_t avg = (Red + Green + Blue) / 3.0;
    

    However, this still won't work, because assigning the value 5.666667 to an integer data type will convert that value to 5. Instead, the result should be rounded to the nearest integer value, which is 6. For this, you can use the functions round or lround:

    uint8_t avg = round((Red + Green + Blue) / 3.0);