E
Eric Sosman
Andrew Poelstra wrote On 05/31/06 00:46,:
It's not necessary, but it's also not sufficient.
The value of `(unsigned int) (~3) + 1' depends on the
way the implementation represents signed integers:
- Two's complement: ~3 is equal to -4, the cast
converts it to UINT_MAX+1-4 == UINT_MAX-3, and
adding 1 gives UINT_MAX-2.
- Ones' complement: ~3 is equal to -3, the cast
converts it to UINT_MAX+1-3 == UINT_MAX-2, and
adding 1 gives UINT_MAX-1.
- Signed magnitude: ~3 is equal to -(INT_MAX-3),
the cast converts it to UINT_MAX+1+INT_MAX-3
== INT_MAX-3 (probably), and adding 1 gives
INT_MAX-2.
You should have written `~(unsigned int)3 + 1',
or simply `~3u + 1' (or even `~3u + 1u').
On the machine mentioned above, mod-and-zero-test took
0.172 seconds to test the numbers 0..999999 for divisibility
by three. Division by repeated subtraction took 474 seconds
to do the same thing. Slowing something down by more than
two hundred seventy-five thousand percent is certainly "a big
difference," but few people would call it an "optimization."
I can't think of a reason for either hints to affect me. Here
is my current code (OP, I'd like some credit for your course):
#include <stdio.h>
#include <math.h>
int main(void)
{
signed int n; /* Best to be explicit about signedness */
unsigned int o; /* in this code. */
printf ("Enter a number: ");
scanf ("%d", &n);
if (n < 0)
{
n += 3; /* Ensure that n isn't INT_MIN */
o = abs(n);
} else {
o = n;
}
/* From now on, o is our variable, and is unsigned. */
/* Note that 0 <= o <= INT_MAX */
while (o >= 3)
o += (unsigned int) (~3) + 1; /* Is this cast necessary? */
It's not necessary, but it's also not sufficient.
The value of `(unsigned int) (~3) + 1' depends on the
way the implementation represents signed integers:
- Two's complement: ~3 is equal to -4, the cast
converts it to UINT_MAX+1-4 == UINT_MAX-3, and
adding 1 gives UINT_MAX-2.
- Ones' complement: ~3 is equal to -3, the cast
converts it to UINT_MAX+1-3 == UINT_MAX-2, and
adding 1 gives UINT_MAX-1.
- Signed magnitude: ~3 is equal to -(INT_MAX-3),
the cast converts it to UINT_MAX+1+INT_MAX-3
== INT_MAX-3 (probably), and adding 1 gives
INT_MAX-2.
You should have written `~(unsigned int)3 + 1',
or simply `~3u + 1' (or even `~3u + 1u').
if (o == 0)
printf ("\nThat number is divisible by 3\n");
else
printf ("\nThat number is not divisible By 3\n");
return 0;
}
For now I'm going to flip through my Discrete Mathematics
textbook and see if I can come up with a cleverer algorithm
for determining 3-divisibility in base 2.
Let's consider that right now I'm running slrn on a 12-year-old
machine, and every so often I boot up a computer that is now about
15 years old to work on. Micro-optimization makes a big difference
on those computers.
On the machine mentioned above, mod-and-zero-test took
0.172 seconds to test the numbers 0..999999 for divisibility
by three. Division by repeated subtraction took 474 seconds
to do the same thing. Slowing something down by more than
two hundred seventy-five thousand percent is certainly "a big
difference," but few people would call it an "optimization."