C陷阱与缺陷 第7章 可移植性缺陷 7.7 除法运算时发生的截断

发布于:2022-12-25 ⋅ 阅读:(168) ⋅ 点赞:(0)

      除法运算时发生的截断 
    q = a / b;
    r = a % b;
    这里,不妨假定b大于0.
    我们希望a,b,q,r之间维持怎样的关系呢?
    1、最重要的一点,我们希望q * b + r == a,因为这是定义余数的关系。
    2、如果我们改变a的正负号,我们希望这会改变q的符号,但这不会改变q的绝对值。
    3、当b>0时,我们希望保证r>=0且r<b。例如,如果余数用于哈希表的索引,确保它是一个有效的索引值很重要。
    但是它们不可能同时成立。
    然而,C语言的定义只保证了第1条形式,以及当a>=0且b>0时,保证|r|<|b|以及r>=0.
    0 <= h < HASHSIZE, n恒为非负,那么我们只需要像下面一样简单地写: 
    h = n % HASHSIZE;
    然而,如果n可能为负数,而此时h也有可能为负,那么这样做就不一定总是合适的了。不过,我们已知h > -HASHSIZE,因此可以这样写:
    h = n % HASHSIZE; 
    if (h < 0) {
        h += HASHSIZE;
    }
    更好的做法是,程序在设计时就应该避免n的值为负这样的情形,并且声明n为无符号数。

    /*
    ** 商和余数。
    */
    #include <stdio.h>
    #include <stdlib.h>

    int main( void ){
        int a, b;
        int quot;
        int rem;

        a = 5;
        b = 3;
        quot = a / b;
        rem = a % b;
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );

        a = -5;
        quot = a / b;
        rem = a % b;
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );

        a = 5;
        b = -3;
        quot = a / b;
        rem = a % b;
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );

        a = -5;
        b = -3;
        quot = a / b;
        rem = a % b;
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );
    
        return EXIT_SUCCESS;
    }

输出:

    /*
    ** 用于索引表。
    */
    #include <stdio.h>
    #include <stdlib.h>
    
    int main( void ){
        int a;
        int b;
        int quot;
        int rem;
    
        a = -5;
        b = 3;
        quot = a / b;
        rem = a % b;
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );
        if( b > 0 ){
            if( rem < 0 ){
                rem += b;
                quot -= 1;
            }
        } else{
            if( rem < 0 ){
                rem += -b;
                quot += 1;
            }
        }
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );
    
        a = -5;
        b = -3;
        quot = a / b;
        rem = a % b;
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );
        if( b > 0 ){
            if( rem < 0 ){
                rem += b;
                quot -= 1;
            }
        } else{
            if( rem < 0 ){
                rem += -b;
                quot += 1;
            }
        }
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );
    
        a = 5;
        b = -3;
        quot = a / b;
        rem = a % b;
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );
        if( b > 0 ){
            if( rem < 0 ){
                rem += b;
                quot -= 1;
            }
        } else{
            if( rem < 0 ){
                rem += -b;
                quot += 1;
            }
        }
        printf( "a = %d, b = %d, quot = %d, rem = %d\n", a, b, quot, rem );
    
        return EXIT_SUCCESS;
    }
输出: