Notes and Talks/UJEP/UPC/02

Number types and operations

Integer types: signed and unsigned, ranges

main.c#include <stdio.h>

void sizes() {
    printf("%ld\n", sizeof(char));
    printf("%ld\n", sizeof(int)); // short int
    printf("%ld\n", sizeof(short));
    printf("%ld\n", sizeof(long));
    printf("%ld\n", sizeof(long long));
    printf("%ld\n", sizeof(float));
    printf("%ld\n", sizeof(double));
}

void signs() {
    printf("%ld\n", sizeof(char));
    printf("%ld\n", sizeof(signed char));
    printf("%ld\n", sizeof(unsigned char));
}

void range() {
    typedef char int_type;
    // typedef signed char int_type;
    // typedef unsigned char int_type;
    // typedef short int_type;
    // ...

    int_type min, max;

    {
        int_type n = 0;
        for (;;) {
            int_type next = n - 1;
            if (next >= n) {
                min = n;
                break;
            }
            n = next;
        }
    }

    {
        int_type n = 0;
        for (;;) {
            int_type next = n + 1;
            if (next <= n) {
                max = n;
                break;
            }
            n = next;
        }
    }

    printf("range: %d - %d\n", min, max);
}

#include <limits.h>
void limits() {
    printf("char: %d - %d\n", CHAR_MIN, CHAR_MAX);
    printf("schar: %d - %d\n", SCHAR_MIN, SCHAR_MAX);
    printf("uchar: %d - %d\n", 0, UCHAR_MAX);
    printf("short: %d - %d\n", SHRT_MIN, SHRT_MAX);
}

#include <stdint.h>

void fixed_limits() {
    int64_t i = INT64_MIN;
    printf("int64_t: %ld - %ld\n", i, INT64_MAX);
}

int main() {
    sizes();
    // signs();
    // range();
    // limits();
    // fixed_limits();
    return 0;
}

Floating-point types

Conversion:

main.c#include <limits.h>
#include <stdio.h>

/* 2's complement */
int const MAXINT_DEC = 2147483647;
int const MAXINT_HEX = 0x7FFFFFFF;

// typedef unsigned int uint;

int main() {
    printf("%d\n", MAXINT_DEC == INT_MAX);
    printf("%d\n", MAXINT_HEX == INT_MAX);

    int i = MAXINT_DEC;

    printf("%d\n", i);
    printf("%d\n", i + 1);

    printf("%u\n", (unsigned int) i);
    printf("%u\n", (unsigned int) i + 1);
    printf("%u\n", i);
    printf("%u\n", i + 1);

    unsigned int ui = (unsigned int) i;

    float f = i;

    printf("%f\n", i);
    printf("%f\n", (float) i);
    printf("%f\n", f);
    printf("%f\n", (float) (i + 1));
    printf("%f\n", (float) (ui + 1));

    return 0;
}

Range and precision:

float.c#include <float.h>
#include <stdio.h>

int main() {
    // precision: ~ 6 decimal digits
    // range: ~ +/- 1.2e-38 .. 3.4e38
    printf("%ld\n", sizeof(float));
    // printf("%f %f %d\n", FLT_MIN, FLT_MAX, FLT_DIG);
    // printf("%g %g %d\n", FLT_MIN, FLT_MAX, FLT_DIG);

    // precision: ~ 15 decimal digits
    // range: ~ +/- 2.2e-308 .. 1.8e308
    printf("%ld\n", sizeof(double));
    // printf("%g %g %d\n", DBL_MIN, DBL_MAX, DBL_DIG);

    // precision is platform-dependent: 64/80/128 bits?
    // 128 bits: quad-precision
    // precision: ~ 18 decimal digits
    // range: ~ +/- 3.4e-4932 .. 1.2e4932
    printf("%ld\n", sizeof(long double));
    // printf("%Lg %Lg %d\n", LDBL_MIN, LDBL_MAX, LDBL_DIG);

    return 0;
}

Pitfalls:

pitfall.c#include <stdio.h>
#include <limits.h>
#include <float.h>

int main() {
    printf("int bits:\t%lu\n", sizeof(int) * CHAR_BIT);
    printf("flt radix:\t%u\n", FLT_RADIX);
    printf("flt mant bits:\t%u\n", FLT_MANT_DIG);

    int cases = 0;
    for(int i = 0; i < INT_MAX; ++i) {
      float f = i;
      int i2 = f;
      if (i != i2) {
        printf("%d != %g (%d)\n", i, f, i2);
        ++cases;
        if (10 <= cases)
          break;
      }
    }

    return 0;
}