473,789 Members | 2,496 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Direct computation of integer limits in K&R2?

Hello all,

In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.

Mar 11 '08
88 3799
Ian Collins wrote, On 11/03/08 21:54:
santosh wrote:
>Ian Collins wrote:
>>santosh wrote:
Hello all,

In K&R2 one exercise asks the reader to compute and print the limits
for the basic integer types. This is trivial for unsigned types. But
is it possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.

Isn't it possible to calculate this based on the unsigned types of the
same size?
Won't this require knowledge of the encoding used, whether twos
complement or sign and magnitude etc?
I think so, I should have added that.
Even if you know it is 2s complement you still can't do it. You need to
know whether sign bit = 1 and all value bits = 0 is a trap or not since
it is allowed to be a trap representation.
--
Flash Gordon
Mar 11 '08 #11
Flash Gordon <sp**@flash-gordon.me.ukwri tes:
Ian Collins wrote, On 11/03/08 21:54:
>santosh wrote:
>>Ian Collins wrote:

santosh wrote:
Hello all,
>
In K&R2 one exercise asks the reader to compute and print the limits
for the basic integer types. This is trivial for unsigned types. But
is it possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.
>
Isn't it possible to calculate this based on the unsigned types of the
same size?
Won't this require knowledge of the encoding used, whether twos
complement or sign and magnitude etc?
I think so, I should have added that.

Even if you know it is 2s complement you still can't do it. You need
to know whether sign bit = 1 and all value bits = 0 is a trap or not
since it is allowed to be a trap representation.
It's only allowed to be a trap representation on _non_ two's
complement representations . sign bit = 1 and all value bits = 0 (and
padding bits at non-trap values) would necessarily be the minimum
representable value.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 12 '08 #12
On Mar 11, 2:37*pm, santosh <santosh....@gm ail.comwrote:
Hello all,

In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.
/*
The standard hearder <limits.hwas introduced on the same page (36)
as the exercise.
We are told to compute the values by standard headers and by direct
computation.
We are also told to determine the ranges of the various floating point
types.

The only hard part I see is the signed integer min and max values
without using <limits.hbecaus e I do not see how you can do it
portably. We can probably deduce the hardware type, but I am not sure
about what guarantees we have as to internal representation. I guess
also we will need separate routines for 2's complement, 1's
complement, sign magnitude, and whatever other types are allowed (e.g.
is decimal storage allowed? I know of CPUs that had BCD instructions
in hardware).

Anyway, here are all the trivial answers:

*/
#include <stdio.h>
#include <limits.h>
#include <float.h>

void floating_limits (void)
{
puts("\nFloatin g point limits:");
printf("DBL_DIG %u\n", (unsigned) DBL_DIG);
printf("DBL_EPS ILON %*.*g\n", DBL_DIG + 3, DBL_DIG,
DBL_EPSILON);
printf("DBL_MAN T_DIG %u\n", (unsigned) DBL_MANT_DIG);
printf("DBL_MAX %*.*g\n", DBL_DIG + 3, DBL_DIG, DBL_MAX);
printf("DBL_MAX _10_EXP %u\n", (unsigned) DBL_MAX_10_EXP) ;
printf("DBL_MAX _EXP %u\n", (unsigned) DBL_MAX_EXP);
printf("DBL_MIN %*.*g\n", DBL_DIG + 3, DBL_DIG, DBL_MIN);
printf("DBL_MIN _10_EXP %d\n", DBL_MIN_10_EXP) ;
printf("DBL_MIN _EXP %d\n", DBL_MIN_EXP);
#ifdef DBL_RADIX
printf("DBL_RAD IX %u\n", (unsigned) DBL_RADIX);
#endif
#ifdef DBL_ROUNDS
printf("DBL_ROU NDS %u\n", (unsigned) DBL_ROUNDS);
#endif
printf("FLT_DIG %u\n", (unsigned) FLT_DIG);
printf("FLT_EPS ILON %*.*g\n", FLT_DIG + 3, FLT_DIG,
FLT_EPSILON);
#ifdef FLT_GUARD
printf("FLT_GUA RD %u\n", (unsigned) FLT_GUARD);
#endif
printf("FLT_MAN T_DIG %u\n", (unsigned) FLT_MANT_DIG);
printf("FLT_MAX %*.*g\n", FLT_DIG + 3, FLT_DIG, FLT_MAX);
printf("FLT_MAX _10_EXP %u\n", (unsigned) FLT_MAX_10_EXP) ;
printf("FLT_MAX _EXP %u\n", (unsigned) FLT_MAX_EXP);
printf("FLT_MIN %*.*g\n", FLT_DIG + 3, FLT_DIG, FLT_MIN);
printf("FLT_MIN _10_EXP %d\n", FLT_MIN_10_EXP) ;
printf("FLT_MIN _EXP %d\n", FLT_MIN_EXP);
printf("LDBL_DI G %u\n", (unsigned) LDBL_DIG);
printf("LDBL_EP SILON %*.*Lg\n", LDBL_DIG + 3, LDBL_DIG, (long
double) LDBL_EPSILON);
printf("LDBL_MA NT_DIG %u\n", (unsigned) LDBL_MANT_DIG);
printf("LDBL_MA X %*.*Lg\n", LDBL_DIG + 3, LDBL_DIG, (long
double) LDBL_MAX);
printf("LDBL_MA X_10_EXP %u\n", (unsigned) LDBL_MAX_10_EXP );
printf("LDBL_MA X_EXP %u\n", (unsigned) LDBL_MAX_EXP);
printf("LDBL_MI N %*.*Lg\n", LDBL_DIG + 3, LDBL_DIG, (long
double) LDBL_MIN);
printf("LDBL_MI N_10_EXP %d\n", LDBL_MIN_10_EXP );
printf("LDBL_MI N_EXP %d\n", LDBL_MIN_EXP);
#ifdef LDBL_RADIX
printf("LDBL_RA DIX %u\n", (unsigned) LDBL_RADIX);
#endif
#ifdef LDBL_ROUNDS
printf("LDBL_RO UNDS %u\n", (unsigned) LDBL_ROUNDS);
#endif
}

void signed_limits_g uarantee(void)
{
static const short shrt_min_est = -32767;
static const short shrt_max_est = +32767;
static const int int_min_est = -32767;
static const int int_max_est = +32767;
static const long long_min_est = -2147483647L;
static const long long_max_est = +2147483647L;
static const long long llong_min_est = -922337203685477 5807LL;
static const long long llong_max_est = +92233720368547 75807LL;
puts("\nSigned limits guaranteed by the standard to be at
least:");
printf("Signed short min %d\n", shrt_min_est);
printf("Signed short max %d\n", shrt_max_est);
printf("Signed int min %d\n", int_min_est);
printf("Signed int max %d\n", int_max_est);
printf("Signed long min %ld\n", long_min_est);
printf("Signed long max %ld\n", long_max_est);
printf("Signed long long min %lld\n", llong_min_est);
printf("Signed long long max %lld\n", llong_max_est);

}

void limits_lookup(v oid)
{
puts("\nLookup from limits.h:");
printf("Width of Char %d\n", CHAR_BIT);
printf("Signed Char max %d\n", CHAR_MAX);
printf("Signed Char min %d\n", CHAR_MIN);
printf("Unsigne d Char max %d\n", UCHAR_MAX);
printf("Signed short min %d\n", SHRT_MIN);
printf("Signed short max %d\n", SHRT_MAX);
printf("Unsigne d short max %u\n", USHRT_MAX);
printf("Signed int min %d\n", INT_MIN);
printf("Signed int max %d\n", INT_MAX);
printf("Unsigne d int max %u\n", UINT_MAX);
printf("Signed long min %ld\n", LONG_MIN);
printf("Signed long max %ld\n", LONG_MAX);
printf("Unsigne d long max %lu\n", ULONG_MAX);
printf("Signed long long min %lld\n", LLONG_MIN);
printf("Signed long long max %lld\n", LLONG_MAX);
printf("Unsigne d long long max %llu\n", ULLONG_MAX);
}

void compute_unsigne d_max(void)
{
unsigned long long ullm = -1;
unsigned um = -1;
unsigned long ulm = -1;
unsigned short usm = -1;
unsigned char ucm = -1;
puts("\nSimple computation of unsigned maximums:");
printf("Unsigne d Char max %d\n", ucm);
printf("Unsigne d short max %u\n", usm);
printf("Unsigne d int max %u\n", um);
printf("Unsigne d long max %lu\n", ulm);
printf("Unsigne d long long max %llu\n", ullm);
}

int main(void)
{
limits_lookup() ;
compute_unsigne d_max();
signed_limits_g uarantee();
floating_limits ();
return 0;
}
Mar 12 '08 #13
On Mar 11, 2:54 pm, Harald van D©¦k <true...@gmail. comwrote:
On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
Hello all,
In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour triggered
by overflow? Remember that the constants in limits.h cannot be used.

#include <stdio.h>
int main(void) {
unsigned u = -1;
int i;
while ((i = u) < 0 || i != u)
u = u >1;
printf("INT_MAX == %u\n", u);

}

This is not guaranteed to work in C99, where the conversion of an out-of-
range integer may raise a signal, but it's valid C90, since the result of
the conversion must be a valid int, and therefore between INT_MIN and
INT_MAX.
What happens if INT_MAX is larger than UINT_MAX? I see no guarantees
that this is not possible.
Mar 12 '08 #14
On Mar 11, 7:30 pm, Micah Cowan <mi...@cowan.na mewrote:
Flash Gordon <s...@flash-gordon.me.ukwri tes:
Ian Collins wrote, On 11/03/08 21:54:
santosh wrote:
Ian Collins wrote:
>>santosh wrote:
Hello all,
>>>In K&R2 one exercise asks the reader to compute and print the limits
for the basic integer types. This is trivial for unsigned types. But
is it possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.
>>Isn't it possible to calculate this based on the unsigned types of the
same size?
Won't this require knowledge of the encoding used, whether twos
complement or sign and magnitude etc?
I think so, I should have added that.
Even if you know it is 2s complement you still can't do it. You need
to know whether sign bit = 1 and all value bits = 0 is a trap or not
since it is allowed to be a trap representation.

It's only allowed to be a trap representation on _non_ two's
complement representations . sign bit = 1 and all value bits = 0 (and
padding bits at non-trap values) would necessarily be the minimum
representable value.
6.5.6.2p2 says ("the first two" below are sign-and-magnitude and
two's complement):

"Which of these applies is implementation-defined, as is whether the
value with sign bit 1 and all value bits zero (for the first two),
or with sign bit and all value bits 1 (for ones' complement), is a
trap representation or a normal value."
Mar 12 '08 #15
On Mar 11, 10:15 pm, user923005 <dcor...@connx. comwrote:
On Mar 11, 2:54 pm, Harald van D©¦k <true...@gmail. comwrote:
On Wed, 12 Mar 2008 03:07:48 +0530, santosh wrote:
Hello all,
In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour triggered
by overflow? Remember that the constants in limits.h cannot be used.
#include <stdio.h>
int main(void) {
unsigned u = -1;
int i;
while ((i = u) < 0 || i != u)
u = u >1;
printf("INT_MAX == %u\n", u);
}
This is not guaranteed to work in C99, where the conversion of an out-of-
range integer may raise a signal, but it's valid C90, since the result of
the conversion must be a valid int, and therefore between INT_MIN and
INT_MAX.

What happens if INT_MAX is larger than UINT_MAX? I see no guarantees
that this is not possible.
6.2.6.2p1-2 say that: INT_MAX = 2**M - 1, UINT_MAX = 2**N - 1,
and M <= N, where M is the number of value bits in int, N is
the number of value bits in unsigned int.
I wonder if there was an implementation where INT_MAX was
equal to UINT_MAX.

Yevgen
Mar 12 '08 #16
mu*****@gmail.c om writes:
On Mar 11, 7:30 pm, Micah Cowan <mi...@cowan.na mewrote:
>Flash Gordon <s...@flash-gordon.me.ukwri tes:
Even if you know it is 2s complement you still can't do it. You need
to know whether sign bit = 1 and all value bits = 0 is a trap or not
since it is allowed to be a trap representation.

It's only allowed to be a trap representation on _non_ two's
complement representations . sign bit = 1 and all value bits = 0 (and
padding bits at non-trap values) would necessarily be the minimum
representabl e value.

6.5.6.2p2 says ("the first two" below are sign-and-magnitude and
two's complement):

"Which of these applies is implementation-defined, as is whether the
value with sign bit 1 and all value bits zero (for the first two),
or with sign bit and all value bits 1 (for ones' complement), is a
trap representation or a normal value."
Huh. I managed to forget that somehow. My bad, Flash.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 12 '08 #17
On Mar 11, 3:01*pm, santosh <santosh....@gm ail.comwrote:
Peter Nilsson wrote:
santosh <santosh....@gm ail.comwrote:
In K&R2 one exercise asks the reader to compute and
print the limits for the basic integer types. This is
trivial for unsigned types. But is it possible for
signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants
in limits.h cannot be used.
Yes. Unlike C99, unsigned to signed integer conversion
is implementation defined without the possibility of
raising a signal. So...
<http://groups.google.c om/group/comp.lang.c/msg/ffe17c645660b76 c>
INT_MIN isn't computed per se, rather it's derived by
determining the representation for negative ints. [I
know pete posted some very simple constant expressions,
though it was some time ago.]

Would you say that this exercise is overly complex for that point in
K&R2?
I will be pretty amazed to see anyone write a portable solution that
does it all (floating point is also requested).
I guess that signed integer <TYPE>_MIN values will be hard to come up
with.

Will computation of DBL_MAX signal a floating point exception?

I guess that it is the hardest exercise in the whole book, by far.
Mar 12 '08 #18
Micah Cowan wrote, On 12/03/08 00:30:
Flash Gordon <sp**@flash-gordon.me.ukwri tes:
>Ian Collins wrote, On 11/03/08 21:54:
>>santosh wrote:
Ian Collins wrote:

santosh wrote:
>Hello all,
>>
>In K&R2 one exercise asks the reader to compute and print the limits
>for the basic integer types. This is trivial for unsigned types. But
>is it possible for signed types without invoking undefined behaviour
>triggere d by overflow? Remember that the constants in limits.h cannot
>be used.
>>
Isn't it possible to calculate this based on the unsigned types of the
same size?
Won't this require knowledge of the encoding used, whether twos
complement or sign and magnitude etc?

I think so, I should have added that.
Even if you know it is 2s complement you still can't do it. You need
to know whether sign bit = 1 and all value bits = 0 is a trap or not
since it is allowed to be a trap representation.

It's only allowed to be a trap representation on _non_ two's
complement representations . sign bit = 1 and all value bits = 0 (and
padding bits at non-trap values) would necessarily be the minimum
representable value.
Wrong. The C standard explicitly allows for it to be a trap
representation on two's complement representations . Quoting from N1256...

| ... If the sign bit is one, the value shall be modiļ¬ed in one of
| the following ways:
| ā€” the corresponding value with sign bit 0 is negated (sign and
| magnitude);
| ā€” the sign bit has the value āˆ’(2 N ) (twoā€™s complement);
| ā€” the sign bit has the value āˆ’(2 N āˆ’ 1) (onesā€™ complement ).
| Which of these applies is implementation-deļ¬ned, as is whether the
| value with sign bit 1 and all value bits zero (for the ļ¬rst two), or
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^
| with sign bit and all value bits 1 (for onesā€™ complement), is a trap
| representation or a normal value. In the case of sign and magnitude
| and onesā€™ complement, if this representation is a normal value it is
| called a negative zero.

two's complement is one of the first two.

The above is from section 6.2.6.2 para 2.
--
Flash Gordon
Mar 12 '08 #19
Micah Cowan wrote, On 12/03/08 05:55:
mu*****@gmail.c om writes:
>On Mar 11, 7:30 pm, Micah Cowan <mi...@cowan.na mewrote:
>>Flash Gordon <s...@flash-gordon.me.ukwri tes:
<snip trap representation in 2s complement>
Huh. I managed to forget that somehow. My bad, Flash.
It's easy to forget. I'm not actually aware of any implementations which
make use of this freedom.
--
Flash Gordon
Mar 12 '08 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.