Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
oorrja
GitHub Repository: oorrja/learntosolveit
Path: blob/master/source/cprogramming/Ex_2.1_cal_limits.rst
1241 views
===============================
Exercise 2.1 - Count the Ranges
===============================

Question
========

Write a program to determine the ranges of char, short, int, and long variables,
both signed and unsigned, by printing appropriate values from standard headers
and by direct computation.  Harder if you compute them: determine the ranges of
the various floating-point types.


.. literalinclude:: ../../languages/cprogs/Ex_2.1_cal_limits.c
   :language: c
   :tab-width: 4

.. runcode:: ../../languages/cprogs/Ex_2.1_cal_limits.c
   :language: c
   :codesite: ideone

Explanation
===========


The execution of the above program will give::

   Minimum Signed Char -128
   Maximum Signed Char 127
   Minimum Signed Short -32768
   Maximum Signed Short 32767
   Minimum Signed Int -2147483648
   Maximum Signed Int 2147483647
   Minimum Signed Long -2147483648
   Maximum signed Long 2147483647
   Maximum Unsigned Char 255
   Maximum Unsigned Short 65535
   Maximum Unsigned Int 4294967295
   Maximum Unsigned Long 4294967295
   

In order explain how we calculate the maximum values, we will have to do some
bit arthimetic. Let's start by calculating the maximum unsigned char.

Sign bit is usually the left most bit of the type. To make it unsigned, we
remove the sign bit and store 0 in it's place.

To represent (unsigned char) 0 = **0000 0000**
To represent it's complement, (unsigned char) ~0 = **1111 1111**

Right Shift 1 will shift that entire sequence to the right and insert 0 from the
left side, so it will give 0111 1111

Converting 0111 1111 to integer will be::

    0 * 2^7 + 1 * 2^ 6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 1 *2^2 + 1 * 2^1 + 1 * 2^0
    = 0 * 0 + 1 * 64 + 1 * 32 + 1 * 16 + 1 * 8 + 1 * 4 + 1 * 2 + 1 * 1
    = 0 + 64 + 32 + 16 + 8 + 4 + 2 + 1
    = 127

That is the maximum signed char value. To get the minimum signed char value, we
look for the number in the other end of the number line.

That is got by, multiplying it by -1 and going one number further to the left in
the number line::

    = - 127 -1
    = -128

So our range is displayed like this::

    -128..-2..-1..0 1 2 3 4... 127

Maximum signed short
--------------------

To get the maximum signed short number, we start with unsigned short type again
and repeat the same operations like we did above.

(short)((unsigned short)~0 >> 1)

In our compiler, a short is 2 bytes

(unsigned short) 0 means **0000 0000 0000 0000**
(unsigned short) ~0 means **1111 1111 1111 1111**

Logical right shift, is we are eliminating the sign bit, which is the left most
bit in the sequence.

(unsigned short)~0 >> 1) 

Take this portion ``1111 1111 1111 111`` 1  and place it as **1111 1111 1111 111**
And then add 0 to the left **0** 1111 1111 1111 111
Rearranging we get **0111 1111 1111 1111**

What is value of 0111 1111 1111 1111 ?

Similar to above::

    =   0 * 2^15 + 1 * 2^14 + 1 * 2^13 + 1 * 2^12 
        + 1 * 2^11 + 1* 2^10 + 1 * 2^9 + 1 * 2^8 
        + 1*2^7 + 1 * 2^6 + 1*2^5 + 1*2^4 
        + 1* 2^3 + 1*2^2 + 1* 2^1 +1*2^0 

        = 16384 + 8192 + 4096 + 2048 + 1024 + 512 + 256 + 128 + 64 + 32 + 16 + 8 + 4 + 2
        = + 1 32767

So, our maximum unsigned short is 32767

Mininum unsigned short will be the negative of that number going one step
further, i.e::

    = -32767 - 1 = -32768

Similarily, we can calculate for int and long types.

For unsigned types, we do not do the shifting (to remove the sign) but simply
print the value of all 1s of the type

(unsigned char)~0;

can be represented as (unsigned char) ~0 = 1111 1111

::

    = 1 * 2^7 + 1 * 2^ 6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 1 *2^2 + 1 * 2^1 + 1 * 2^0
    = 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
    = 255



.. seealso::

   * :c-suggest-improve:`Ex_2.1_cal_limits.c`
   * :c-better-explain:`Ex_2.1_cal_limits.rst`