Do I need to explicitly handle negative numbers or zero when summing squared digits?

前端 未结 9 1222
無奈伤痛
無奈伤痛 2021-01-30 01:51

I recently had a test in my class. One of the problems was the following:

Given a number n, write a function in C/C++ that returns the su

9条回答
  •  星月不相逢
    2021-01-30 02:21

    NOTE: AS I was writing this answer, you did clarify that you are using C. The majority of my answer is about C++. However, since your title still has C++ and the question is still tagged C++, I have chosen to answer anyway in case this is still useful to other people, especially since most of the answers I've seen till now are mostly unsatisfactory.

    In modern C++ (Note: I don't really know where C stands on this), your professor seems to be wrong on both counts.

    First is this part right here:

    if (n == 0) {
            return 0;
    }
    

    In C++, this is basically the same thing as:

    if (!n) {
            return 0;
    }
    

    That means your while is equivalent to something like this:

    while(n != 0) {
        // some implementation
    }
    

    That means since you are merely exiting in your if when the while wouldn't execute anyway, there really isn't a reason to put this if here, since what you are doing after the loop and in the if are equivalent anyway. Although I should say that is for some reason these were different, you'd need to have this if.

    So really, this if statement isn't particularly useful unless I'm mistaken.

    The second part is where things get hairy:

    if (n < 0) {
        n = n * (-1);
    }  
    

    The heart of the issue is is what the output of the modulus of a negative number outputs.

    In modern C++, this seems to be mostly well defined:

    The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined. For integral operands the / operator yields the algebraic quotient with any fractional part discarded; if the quotient a/b is representable in the type of the result, (a/b)*b + a%b is equal to a.

    And later:

    If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined.

    As the poster of the quoted answer correctly points out, the important part of this equation right here:

    (a/b)*b + a%b

    Taking an example of your case, you'd get something like this:

    -13/ 10 = -1 (integer truncation)
    -1 * 10 = -10
    -13 - (-10) = -13 + 10 = -3 
    

    The only catch is that last line:

    If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined.

    That means that in a case like this, only the sign seems to be implementation-defined. That shouldn't be a problem in your case because, because you are squaring this value anyway.

    That said, keep in mind that this doesn't necessarily apply to earlier versions of C++, or C99. If that is what your professor is using, that could be why.


    EDIT: Nope, I'm wrong. This seems to be the case for C99 or later as well:

    C99 requires that when a/b is representable:

    (a/b) * b + a%b shall equal a

    And another place:

    When integers are divided and the division is inexact, if both operands are positive the result of the / operator is the largest integer less than the algebraic quotient and the result of the % operator is positive. If either operand is negative, whether the result of the / operator is the largest integer less than the algebraic quotient or the smallest integer greater than the algebraic quotient is implementation-defined, as is the sign of the result of the % operator. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.

    Does either ANSI C or ISO C specify what -5 % 10 should be?

    So, yeah. Even in C99, this doesn't seem to affect you. The equation is the same.

提交回复
热议问题