Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #85177 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2016-03-28 01:34 -0700 |
| Last post | 2016-04-11 20:32 +0100 |
| Articles | 20 on this page of 43 — 10 participants |
Back to article view | Back to comp.lang.c
K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-03-28 01:34 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-03-28 01:36 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Barry Schwarz <schwarzb@dqel.com> - 2016-03-28 10:08 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-03-28 11:55 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-03-28 12:08 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Barry Schwarz <schwarzb@dqel.com> - 2016-03-28 11:37 -0700
Re: K&R exercise 3-4 handle largest negative number implementation supercat@casperkitty.com - 2016-03-28 13:11 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Barry Schwarz <schwarzb@dqel.com> - 2016-03-28 18:16 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-03-29 03:17 +0100
Re: K&R exercise 3-4 handle largest negative number implementation Barry Schwarz <schwarzb@dqel.com> - 2016-03-28 22:10 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-03-29 11:39 +0100
Re: K&R exercise 3-4 handle largest negative number implementation Keith Thompson <kst-u@mib.org> - 2016-03-29 08:56 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Keith Thompson <kst-u@mib.org> - 2016-03-29 12:31 -0700
Re: K&R exercise 3-4 handle largest negative number implementation supercat@casperkitty.com - 2016-03-30 09:54 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Keith Thompson <kst-u@mib.org> - 2016-03-30 12:03 -0700
Re: K&R exercise 3-4 handle largest negative number implementation supercat@casperkitty.com - 2016-03-30 14:00 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-03-30 03:41 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Barry Schwarz <schwarzb@dqel.com> - 2016-03-30 10:26 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-04-01 04:41 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Richard Heathfield <rjh@cpax.org.uk> - 2016-04-01 13:33 +0100
Re: K&R exercise 3-4 handle largest negative number implementation Barry Schwarz <schwarzb@dqel.com> - 2016-04-01 09:23 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-04-01 04:53 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Barry Schwarz <schwarzb@dqel.com> - 2016-04-01 09:10 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-04-02 00:41 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-04-02 11:07 +0100
Re: K&R exercise 3-4 handle largest negative number implementation Alla _ <modelling.data@gmail.com> - 2016-04-02 01:03 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Tim Rentsch <txr@alumni.caltech.edu> - 2016-03-30 10:05 -0700
Re: K&R exercise 3-4 handle largest negative number implementation supercat@casperkitty.com - 2016-03-30 10:15 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Tim Rentsch <txr@alumni.caltech.edu> - 2016-04-05 12:25 -0700
Re: K&R exercise 3-4 handle largest negative number implementation supercat@casperkitty.com - 2016-04-05 14:09 -0700
Re: K&R exercise 3-4 handle largest negative number implementation asetofsymbols@gmail.com - 2016-04-05 22:49 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Richard Heathfield <rjh@cpax.org.uk> - 2016-04-06 07:16 +0100
Re: K&R exercise 3-4 handle largest negative number implementation BartC <bc@freeuk.com> - 2016-04-06 11:24 +0100
Re: K&R exercise 3-4 handle largest negative number implementation asetofsymbols@gmail.com - 2016-04-06 10:27 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-04-06 11:46 +0100
Re: K&R exercise 3-4 handle largest negative number implementation Richard Heathfield <rjh@cpax.org.uk> - 2016-04-06 12:48 +0100
Re: K&R exercise 3-4 handle largest negative number implementation supercat@casperkitty.com - 2016-04-06 08:36 -0700
Re: K&R exercise 3-4 handle largest negative number implementation supercat@casperkitty.com - 2016-04-06 07:59 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Tim Rentsch <txr@alumni.caltech.edu> - 2016-05-05 11:51 -0700
Re: K&R exercise 3-4 handle largest negative number implementation programming109@gmail.com - 2016-04-11 07:25 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-04-11 19:38 +0100
Re: K&R exercise 3-4 handle largest negative number implementation programming109@gmail.com - 2016-04-11 12:14 -0700
Re: K&R exercise 3-4 handle largest negative number implementation Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-04-11 20:32 +0100
Page 1 of 3 [1] 2 3 Next page →
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2016-03-28 01:34 -0700 |
| Subject | K&R exercise 3-4 handle largest negative number implementation |
| Message-ID | <d1bcdf9a-bb8c-4783-ac20-71ff2eb1a5b2@googlegroups.com> |
Hello!
Please, take a look at my solution for exercise 3-4. What do you think?
[quote]
In a two's complement number representation, our version of
itoa (I am publishing the initial version of itoa below)
does not handle the largest negative number, that is, the value
of n equal to -(2^(wordsize-l)). Modify it to print that value
correctly, regardless of the machine on which it runs.[/quote]
To test the function I had to add atoi function as well; it's
from K&R, hence no need to check that.
Original itoa by K&R:
// convert number to a character string
void itoa_function(int n, char *string)
{
int i, sign;
//record sign, make it positive
if((sign = n) < 0)
n = -n;
i = 0;
//generate digits in reverse order
do
{
string[i++] = n % 10 + '0';
} while ((n /= 10) > 0);
if (sign < 0)
string[i++] = '-';
string[i] = '\0';
reverse(string);
}
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
int atoi_function(char *string);
void itoa_function(int n, char *string);
void reverse(char *string);
int main(int argc, char **argv)
{
char string[1024];
int n;
if (argc < 2)
{
printf("Usage: ./program and number\n");
return -1;
}
for (int i = 1; i < argc; i++)
{
n = atoi_function(argv[i]);
itoa_function(n, string);
printf("\"%d\" => \"%s\"\n", n, string);
}
return 0;
}
// convert string to integer
int atoi_function(char *string)
{
int i, n, sign;
//skip white space
for (i = 0; isspace(string[i]); i++);
sign = (string[i] == '-') ? -1 : 1;
//skip sign
if (string[i] == '+' || string[i] == '-')
i++;
for (n = 0; isdigit(string[i]); i++)
n = 10 * n + (string[i] - '0');
return sign * n;
}
// convert number to a character string
// exercise 3-4, handle largest negative number
void itoa_function(int n, char *string)
{
int new_n = n;
int i, sign;
//record sign, make it positive
if((sign = new_n) < 0)
{
if (n == INT_MIN)
new_n += 1;
new_n = -new_n;
printf("%d\n", new_n);
}
i = 0;
//generate digits in reverse order
do
{
string[i++] = new_n % 10 + '0';
} while ((new_n /= 10) > 0);
if (n == INT_MIN)
string[0] += 1;
if (sign < 0)
string[i++] = '-';
string[i] = '\0';
reverse(string);
}
/*************
// convert number to a character string
// exercise 3-4, test negative limiting number
void itoa_function(int n, char *string)
{
int new_n = n;
int i, sign;
//record sign, make it positive
if((sign = new_n) < 0)
{
if (n == -595)
new_n += 1;
new_n = -new_n;
printf("%d\n", new_n);
}
i = 0;
//generate digits in reverse order
do
{
string[i++] = new_n % 10 + '0';
} while ((new_n /= 10) > 0);
if (n == -595)
string[0] += 1;
if (sign < 0)
string[i++] = '-';
string[i] = '\0';
reverse(string);
}
******************/
void reverse(char *string)
{
int c;
for (int i = 0, j = strlen(string) - 1;
i < j; i++, j--)
{
c = string[i];
string[i] = string[j];
string[j] = c;
}
}
Thank you!
[toc] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2016-03-28 01:36 -0700 |
| Message-ID | <15e40a0d-5330-4cd3-b69a-e7da7e5fc97f@googlegroups.com> |
| In reply to | #85177 |
<snip> I have tested with -2147483648 (and with arbitrary limiting number such as -595 manually typed in for n, as you can see in the test version of the new function).
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2016-03-28 10:08 -0700 |
| Message-ID | <h4pifb54d9n587tq42718v95qepbbleo49@4ax.com> |
| In reply to | #85177 |
On Mon, 28 Mar 2016 01:34:13 -0700 (PDT), Alla _ <modelling.data@gmail.com> wrote: >Hello! > >Please, take a look at my solution for exercise 3-4. What do you think? What happened to your hash table project? Did you ever solve the problem with apostrophes? Since none of us could find it in your code, maybe you can tell us what it was so we can all learn. -- Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2016-03-28 11:55 -0700 |
| Message-ID | <148c7739-5d0c-462d-9bc4-9f86418dcd32@googlegroups.com> |
| In reply to | #85192 |
On Monday, March 28, 2016 at 10:48:21 PM UTC+4, Barry Schwarz wrote: > On Mon, 28 Mar 2016 01:34:13 -0700 (PDT), Alla _ > <modelling.data@gmail.com> wrote: > > >Hello! > > > >Please, take a look at my solution for exercise 3-4. What do you think? > > What happened to your hash table project? Did you ever solve the > problem with apostrophes? Since none of us could find it in your > code, maybe you can tell us what it was so we can all learn. > Oh, sorry! Sure! I will now post the answer to apostrophe issue in hashtable thread.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2016-03-28 12:08 -0700 |
| Message-ID | <b7836912-49d2-442b-8575-84c5e43d3845@googlegroups.com> |
| In reply to | #85192 |
On Monday, March 28, 2016 at 10:48:21 PM UTC+4, Barry Schwarz wrote: > On Mon, 28 Mar 2016 01:34:13 -0700 (PDT), Alla _ > <modelling.data@gmail.com> wrote: > > >Hello! > > > >Please, take a look at my solution for exercise 3-4. What do you think? > > What happened to your hash table project? Did you ever solve the > problem with apostrophes? Since none of us could find it in your > code, maybe you can tell us what it was so we can all learn. > I am taking a break from the hashtable project, to let it settle ) But I have to come back to it, because I have unresolved issues such as taking out all those global variables. It's on my list-to-do for sure.
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2016-03-28 11:37 -0700 |
| Message-ID | <glpifb1eh94iv045hugjqv596t3tn78pcm@4ax.com> |
| In reply to | #85177 |
On Mon, 28 Mar 2016 01:34:13 -0700 (PDT), Alla _
<modelling.data@gmail.com> wrote:
>Hello!
>
>Please, take a look at my solution for exercise 3-4. What do you think?
>
>[quote]
>In a two's complement number representation, our version of
>itoa (I am publishing the initial version of itoa below)
>does not handle the largest negative number, that is, the value
>of n equal to -(2^(wordsize-l)). Modify it to print that value
>correctly, regardless of the machine on which it runs.[/quote]
>
>To test the function I had to add atoi function as well; it's
>from K&R, hence no need to check that.
Why not use strtol instead of something homegrown? At the very least
it would eliminate the possibility of typing errors as you transcribe
it from K&R.
<snip original K&R itoa>
>#include <stdio.h>
>#include <string.h>
>#include <ctype.h>
>#include <limits.h>
>
>int atoi_function(char *string);
>void itoa_function(int n, char *string);
>void reverse(char *string);
>
>int main(int argc, char **argv)
>{
> char string[1024];
> int n;
>
> if (argc < 2)
> {
> printf("Usage: ./program and number\n");
> return -1;
> }
>
> for (int i = 1; i < argc; i++)
> {
> n = atoi_function(argv[i]);
> itoa_function(n, string);
>
> printf("\"%d\" => \"%s\"\n", n, string);
There are a few issues here:
1 - Requiring the user to visually compare two ten digit values is
error prone.
2 - If there is an error in your atoi function, the printout values
will still match but not with the input value. It is possible that
such an error could prevent itoa from processing some corner case.
This would make it impossible to fully test itoa.
3 - I think it would be better to compare string and argv[i]. And
rather than have the user do in manually, you could use strcmp? (Yes,
this requires some additional work if the input has leading zeros.
Ignoring leading zeros was one of the few uses I found for strspn.)
> }
>
> return 0;
>}
<snip atoi>
>// convert number to a character string
>// exercise 3-4, handle largest negative number
>void itoa_function(int n, char *string)
>{
> int new_n = n;
> int i, sign;
>
> //record sign, make it positive
> if((sign = new_n) < 0)
> {
> if (n == INT_MIN)
> new_n += 1;
> new_n = -new_n;
> printf("%d\n", new_n);
> }
> i = 0;
> //generate digits in reverse order
> do
> {
> string[i++] = new_n % 10 + '0';
>
> } while ((new_n /= 10) > 0);
>
> if (n == INT_MIN)
> string[0] += 1;
This "trick" works only because in two's complement representation it
is not possible for the unit digit of INT_MIN to be 9. That is what
the exercise requested but the standard allows other than two's
complement.
I wonder why K&R thought it advisable to work only with positive
values. The process of repeatedly using % and / works just as well
with negative numbers if you use the absolute value of the remainder.
When you do it that way, INT_MIN presents no special issue.
> if (sign < 0)
> string[i++] = '-';
> string[i] = '\0';
> reverse(string);
>}
<snip commented code not part of project>
>void reverse(char *string)
>{
> int c;
> for (int i = 0, j = strlen(string) - 1;
> i < j; i++, j--)
> {
> c = string[i];
> string[i] = string[j];
> string[j] = c;
> }
>}
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-03-28 13:11 -0700 |
| Message-ID | <c7f1b100-3a36-4b3b-bfb1-72153c3d55de@googlegroups.com> |
| In reply to | #85193 |
On Monday, March 28, 2016 at 1:48:35 PM UTC-5, Barry Schwarz wrote:
> I wonder why K&R thought it advisable to work only with positive
> values. The process of repeatedly using % and / works just as well
> with negative numbers if you use the absolute value of the remainder.
> When you do it that way, INT_MIN presents no special issue.
K&R didn't specify whether "%" and "/" use Euclidian or truncated division
semantics. Further, even if they had specified truncated division semantics,
having to take the absolute value of each digit will on most platforms
require a fair bit of extra work for each iteration compared with simply
saying:
unsigned long l=n;
if (n < 0)
{
printf("-");
l=-l; // Not reliant upon two's-complement representation
}
The only implementations upon which that won't work are those where
0UL-LNG_MIN is not representable as unsigned long; such implementations
are extremely rare.
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2016-03-28 18:16 -0700 |
| Message-ID | <bpljfbdp362mgeamf62mqktdn8jqr3o2pq@4ax.com> |
| In reply to | #85200 |
On Mon, 28 Mar 2016 13:11:59 -0700 (PDT), supercat@casperkitty.com wrote: >On Monday, March 28, 2016 at 1:48:35 PM UTC-5, Barry Schwarz wrote: >> I wonder why K&R thought it advisable to work only with positive >> values. The process of repeatedly using % and / works just as well >> with negative numbers if you use the absolute value of the remainder. >> When you do it that way, INT_MIN presents no special issue. > >K&R didn't specify whether "%" and "/" use Euclidian or truncated division >semantics. Further, even if they had specified truncated division semantics, I don't know what you mean by Euclidian division but page 41 of K&R2 specifies truncated division. -- Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-03-29 03:17 +0100 |
| Message-ID | <8760w6yqly.fsf@bsb.me.uk> |
| In reply to | #85217 |
Barry Schwarz <schwarzb@dqel.com> writes: > On Mon, 28 Mar 2016 13:11:59 -0700 (PDT), supercat@casperkitty.com > wrote: > >>On Monday, March 28, 2016 at 1:48:35 PM UTC-5, Barry Schwarz wrote: >>> I wonder why K&R thought it advisable to work only with positive >>> values. The process of repeatedly using % and / works just as well >>> with negative numbers if you use the absolute value of the remainder. >>> When you do it that way, INT_MIN presents no special issue. >> >>K&R didn't specify whether "%" and "/" use Euclidian or truncated division >>semantics. Further, even if they had specified truncated division semantics, > > I don't know what you mean by Euclidian division but page 41 of K&R2 > specifies truncated division. It's not a commonly used term but it refers to the "other" division and remainder operation that K&R1 and C90 permitted -- Euclidean division always has a positive remainder. When both operands are positive a/b and a%b are both positive, but when either is negative, C90 permits either sign for a%b. Since you always have (a/b)*b + a%b = a (provided a/b does not overflow) this choice also affect the result of the division. Since C99 (and later) you always get truncating division but I'm not sure why K&R2 would be more specific than the standard that confirmed their earlier text. Are you sure it says truncation in all cases? -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2016-03-28 22:10 -0700 |
| Message-ID | <jb3kfb9lgigqfitg32qehrgn52ea63qlie@4ax.com> |
| In reply to | #85218 |
On Tue, 29 Mar 2016 03:17:45 +0100, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote: >Barry Schwarz <schwarzb@dqel.com> writes: > >> On Mon, 28 Mar 2016 13:11:59 -0700 (PDT), supercat@casperkitty.com >> wrote: >> >>>On Monday, March 28, 2016 at 1:48:35 PM UTC-5, Barry Schwarz wrote: >>>> I wonder why K&R thought it advisable to work only with positive >>>> values. The process of repeatedly using % and / works just as well >>>> with negative numbers if you use the absolute value of the remainder. >>>> When you do it that way, INT_MIN presents no special issue. >>> >>>K&R didn't specify whether "%" and "/" use Euclidian or truncated division >>>semantics. Further, even if they had specified truncated division semantics, >> >> I don't know what you mean by Euclidian division but page 41 of K&R2 >> specifies truncated division. > >It's not a commonly used term but it refers to the "other" division and >remainder operation that K&R1 and C90 permitted -- Euclidean division >always has a positive remainder. When both operands are positive a/b >and a%b are both positive, but when either is negative, C90 permits >either sign for a%b. Since you always have (a/b)*b + a%b = a (provided >a/b does not overflow) this choice also affect the result of the >division. > >Since C99 (and later) you always get truncating division but I'm not >sure why K&R2 would be more specific than the standard that confirmed >their earlier text. Are you sure it says truncation in all cases? My copy of page 41 starts: "2.5 Arithmetic Operators The binary arithmetic operators are +, -, *, /, and the modulus operator %. Integer division truncates any fractional part." It doesn't say all but there no qualification either. -- Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-03-29 11:39 +0100 |
| Message-ID | <87r3ety3dm.fsf@bsb.me.uk> |
| In reply to | #85221 |
Barry Schwarz <schwarzb@dqel.com> writes: > On Tue, 29 Mar 2016 03:17:45 +0100, Ben Bacarisse > <ben.usenet@bsb.me.uk> wrote: > >>Barry Schwarz <schwarzb@dqel.com> writes: >> >>> On Mon, 28 Mar 2016 13:11:59 -0700 (PDT), supercat@casperkitty.com >>> wrote: >>> >>>>On Monday, March 28, 2016 at 1:48:35 PM UTC-5, Barry Schwarz wrote: >>>>> I wonder why K&R thought it advisable to work only with positive >>>>> values. The process of repeatedly using % and / works just as well >>>>> with negative numbers if you use the absolute value of the remainder. >>>>> When you do it that way, INT_MIN presents no special issue. >>>> >>>>K&R didn't specify whether "%" and "/" use Euclidian or truncated division >>>>semantics. Further, even if they had specified truncated division semantics, >>> >>> I don't know what you mean by Euclidian division but page 41 of K&R2 >>> specifies truncated division. >> >>It's not a commonly used term but it refers to the "other" division and >>remainder operation that K&R1 and C90 permitted -- Euclidean division >>always has a positive remainder. When both operands are positive a/b >>and a%b are both positive, but when either is negative, C90 permits >>either sign for a%b. Since you always have (a/b)*b + a%b = a (provided >>a/b does not overflow) this choice also affect the result of the >>division. >> >>Since C99 (and later) you always get truncating division but I'm not >>sure why K&R2 would be more specific than the standard that confirmed >>their earlier text. Are you sure it says truncation in all cases? > > My copy of page 41 starts: > > "2.5 Arithmetic Operators > > The binary arithmetic operators are +, -, *, /, and the modulus > operator %. Integer division truncates any fractional part." > > It doesn't say all but there no qualification either. Curious. I wonder why. K&R2 slightly pre-dates the standard, so maybe requiring the new semantics was in the draft right up to the very end. K&R's errata don't mention the discrepancy. The C99 Rationale says: "In C89, division of integers involving negative operands could round upward or downward in an implementation-defined manner; the intent was to avoid incurring overhead in run-time code to check for special cases and enforce specific behavior. In Fortran, however, the result will always truncate toward zero, and the overhead seems to be acceptable to the numeric programming community. Therefore, C99 now requires similar behavior, which should facilitate porting of code from Fortran to C." The functions div and ldiv give you C99 semantics even on a C90 implementation and that's probably the way I'd go for this exercise. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-03-29 08:56 -0700 |
| Message-ID | <lny4911dn6.fsf@kst-u.example.com> |
| In reply to | #85217 |
Barry Schwarz <schwarzb@dqel.com> writes:
> On Mon, 28 Mar 2016 13:11:59 -0700 (PDT), supercat@casperkitty.com
> wrote:
>>On Monday, March 28, 2016 at 1:48:35 PM UTC-5, Barry Schwarz wrote:
>>> I wonder why K&R thought it advisable to work only with positive
>>> values. The process of repeatedly using % and / works just as well
>>> with negative numbers if you use the absolute value of the remainder.
>>> When you do it that way, INT_MIN presents no special issue.
>>
>>K&R didn't specify whether "%" and "/" use Euclidian or truncated division
>>semantics. Further, even if they had specified truncated division semantics,
>
> I don't know what you mean by Euclidian division but page 41 of K&R2
> specifies truncated division.
I'm guessing supercat is referring to K&R1 (or perhaps to Kernighan
and Ritchie themselves). I'll check my copy of K&R1 later today.
supercat: If you're referring to Brian Kernighan and Dennis Ritchie,
I suggest not abbreviating their names to "K&R". That term almost
universally refers to the book, not the people.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-03-29 12:31 -0700 |
| Message-ID | <ln8u1113ov.fsf@kst-u.example.com> |
| In reply to | #85238 |
Keith Thompson <kst-u@mib.org> writes:
> Barry Schwarz <schwarzb@dqel.com> writes:
>> On Mon, 28 Mar 2016 13:11:59 -0700 (PDT), supercat@casperkitty.com
>> wrote:
>>>On Monday, March 28, 2016 at 1:48:35 PM UTC-5, Barry Schwarz wrote:
>>>> I wonder why K&R thought it advisable to work only with positive
>>>> values. The process of repeatedly using % and / works just as well
>>>> with negative numbers if you use the absolute value of the remainder.
>>>> When you do it that way, INT_MIN presents no special issue.
>>>
>>>K&R didn't specify whether "%" and "/" use Euclidian or truncated
>>>division semantics. Further, even if they had specified truncated
>>>division semantics,
>>
>> I don't know what you mean by Euclidian division but page 41 of K&R2
>> specifies truncated division.
>
> I'm guessing supercat is referring to K&R1 (or perhaps to Kernighan
> and Ritchie themselves). I'll check my copy of K&R1 later today.
>
> supercat: If you're referring to Brian Kernighan and Dennis Ritchie,
> I suggest not abbreviating their names to "K&R". That term almost
> universally refers to the book, not the people.
Here's what K&R1 says about division (section 7.3 in the reference
manual appendix):
The binary / operator indicates division. When positive integers
are divided truncation is toward 0, but the form of truncation is
machine-dependent if either operand is negative. On all machines
covered by this manual, the remainder has the same sign as the
dividend. It is always true that (a/b)*b + a%b is equal to a (if b
is not 0).
The binary % operator yields the remainder from the division of the
first expression by the second. The usual arithmetic conversions
are performed. The operands must not be float.
(I presume the omission of double was unintentional.)
K&R2 says:
[...] If both operands are non-negative, then the remainder is
non-negative and smaller than the divisor; if not, it is guaranteed
only that the absolute value of the remainder is smaller than the
absolute value of the divisor.
C99 changed the rules for integer division, requiring truncation toward
zero.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-03-30 09:54 -0700 |
| Message-ID | <5caca6ab-a075-4462-b0e1-ed74057955a5@googlegroups.com> |
| In reply to | #85262 |
On Tuesday, March 29, 2016 at 2:31:38 PM UTC-5, Keith Thompson wrote: > C99 changed the rules for integer division, requiring truncation toward > zero. I sometimes get confused with some of the differences between K&R2 and the C89/C90 Standard. I find it curious that C90 chose to loosen things compared to K&R2 but C99 chose to restore things to the pre-C90 state of affairs. I also find it interesting that a behavior which was chosen to make things simplest for ancient hardware is actually more expensive in many cases on modern hardware than would be Euclidian division/modulus (in a lot of hardware, division by most constants could be handled by doing a multiply- by-constant and ignoring the lower word, but the required signed-division hardware needs an extra step to correct negative results).
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-03-30 12:03 -0700 |
| Message-ID | <lnvb43yei8.fsf@kst-u.example.com> |
| In reply to | #85358 |
supercat@casperkitty.com writes:
> On Tuesday, March 29, 2016 at 2:31:38 PM UTC-5, Keith Thompson wrote:
>> C99 changed the rules for integer division, requiring truncation toward
>> zero.
>
> I sometimes get confused with some of the differences between K&R2 and the
> C89/C90 Standard.
In principle, there is no difference; K&R2 describes the language
defined by the 1989 ANSI C standard (which is the same language
described by the 1990 ISO C standard). K&R2's description is less
rigorous.
What differences to you see?
> I find it curious that C90 chose to loosen things compared
> to K&R2 but C99 chose to restore things to the pre-C90 state of affairs.
I don't believe that's accurate -- nor, as far as I know, is the C99
behavior the same as "the pre-C90 state of affairs".
> I also find it interesting that a behavior which was chosen to make
> things simplest for ancient hardware is actually more expensive in
> many cases on modern hardware than would be Euclidian division/modulus
> (in a lot of hardware, division by most constants could be handled by
> doing a multiply- by-constant and ignoring the lower word, but the
> required signed-division hardware needs an extra step to correct
> negative results).
The C99 rationale says:
In C89, division of integers involving negative operands could
round upward or downward in an implementation-defined manner; the
intent was to avoid incurring overhead in run-time code to check
for special cases and enforce specific behavior. In Fortran,
however, the result will always truncate toward zero, and the
overhead seems to be acceptable to the numeric programming
community. Therefore, C99 now requires similar behavior, which
should facilitate porting of code from Fortran to C. The table in
ยง7.20.6.2 of this document illustrates the required semantics.
C89/C90 has the div() and ldiv() functions (C99 added lldiv())
which specify the truncate toward zero behavior when the "/" and
"%" operators didn't specify it. With C99's change to specify
the behavior of "/" and "%" more precisely, those functions are
not as useful, but they can still be used to get both results in
one operation.
(Personally, I find a definition where, for example, -7 % 5 yields
3 rather than -2 to make more mathematical sense, but apparently
the Fortran numeric programming community doesn't share my opinion.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-03-30 14:00 -0700 |
| Message-ID | <fe162679-0191-4b83-8b00-c47200a13b57@googlegroups.com> |
| In reply to | #85373 |
On Wednesday, March 30, 2016 at 2:03:54 PM UTC-5, Keith Thompson wrote: > > I sometimes get confused with some of the differences between K&R2 and the > > C89/C90 Standard. > > In principle, there is no difference; K&R2 describes the language > defined by the 1989 ANSI C standard (which is the same language > described by the 1990 ISO C standard). K&R2's description is less > rigorous. Never mind--brain glitch. I misinterpreted the fact that things hadn't changed between K&R1 and K&R2 and the earlier claim that K&R2 specified truncating division as implying that K&R differed from ANSI [in fact, K&R2 allows either truncating or Euclidian division].
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2016-03-30 03:41 -0700 |
| Message-ID | <e86535de-fe61-47b1-9f12-06dd56a950ca@googlegroups.com> |
| In reply to | #85193 |
On Monday, March 28, 2016 at 10:48:35 PM UTC+4, Barry Schwarz wrote:
> On Mon, 28 Mar 2016 01:34:13 -0700 (PDT), Alla _
> <modelling.data@gmail.com> wrote:
>
> >Hello!
> >
> >Please, take a look at my solution for exercise 3-4. What do you think?
> >
> >[quote]
> >In a two's complement number representation, our version of
> >itoa (I am publishing the initial version of itoa below)
> >does not handle the largest negative number, that is, the value
> >of n equal to -(2^(wordsize-l)). Modify it to print that value
> >correctly, regardless of the machine on which it runs.[/quote]
> >
> >To test the function I had to add atoi function as well; it's
> >from K&R, hence no need to check that.
>
> Why not use strtol instead of something homegrown? At the very least
> it would eliminate the possibility of typing errors as you transcribe
> it from K&R.
I am learning, and I like to use self-made functions, or functions
suggested by K&R.
<snip>
> There are a few issues here:
>
> 1 - Requiring the user to visually compare two ten digit values is
> error prone.
>
> 2 - If there is an error in your atoi function, the printout values
> will still match but not with the input value. It is possible that
> such an error could prevent itoa from processing some corner case.
> This would make it impossible to fully test itoa.
>
> 3 - I think it would be better to compare string and argv[i]. And
> rather than have the user do in manually, you could use strcmp? (Yes,
> this requires some additional work if the input has leading zeros.
> Ignoring leading zeros was one of the few uses I found for strspn.)
>
Please, take a look at this version. Have I implemented
correctly what you were referring to?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
int atoi_function(char *string);
void itoa_function(int n, char *string);
void reverse(char *string);
int equal_strings(char *string1, char *string2);
int main(int argc, char **argv)
{
char string[1024];
int n, m;
if (argc < 2)
{
printf("Usage: ./program and number\n");
return -1;
}
for (int i = 1; i < argc; i++)
{
n = atoi_function(argv[i]);
itoa_function(n, string);
if ((m = equal_strings(argv[i], string)) == 0)
printf("\"%d\" => \"%s\"\n", n, string);
else
printf("Error\n");
}
return 0;
}
// check if the input and output strings are equal
int equal_strings(char *string1, char *string2)
{
while (*string1 && (*string1 == 0))
string1 += 1;
while (*string2 && (*string2 == 0))
string2 += 1;
return strcmp(string1, string2);
}
// convert string to integer
int atoi_function(char *string)
{
int i, n, sign;
//skip white space
for (i = 0; isspace(string[i]); i++);
sign = (string[i] == '-') ? -1 : 1;
//skip sign
if (string[i] == '+' || string[i] == '-')
i++;
for (n = 0; isdigit(string[i]); i++)
n = 10 * n + (string[i] - '0');
return sign * n;
}
// convert number to a character string
// exercise 3-4, handle largest negative number
void itoa_function(int n, char *string)
{
int new_n = n;
int i, sign;
i = 0;
//generate digits in reverse order
do
{
string[i++] = abs(new_n % 10) + '0';
} while ((abs(new_n /= 10)) > 0);
if ((sign = n) < 0)
string[i++] = '-';
string[i] = '\0';
reverse(string);
}
void reverse(char *string)
{
int c;
for (int i = 0, j = strlen(string) - 1;
i < j; i++, j--)
{
c = string[i];
string[i] = string[j];
string[j] = c;
}
}
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2016-03-30 10:26 -0700 |
| Message-ID | <l51ofbliquaru6nedi48c61g7olc3vitlv@4ax.com> |
| In reply to | #85306 |
On Wed, 30 Mar 2016 03:41:54 -0700 (PDT), Alla _
<modelling.data@gmail.com> wrote:
>On Monday, March 28, 2016 at 10:48:35 PM UTC+4, Barry Schwarz wrote:
<snip>
>> There are a few issues here:
>>
>> 1 - Requiring the user to visually compare two ten digit values is
>> error prone.
>>
>> 2 - If there is an error in your atoi function, the printout values
>> will still match but not with the input value. It is possible that
>> such an error could prevent itoa from processing some corner case.
>> This would make it impossible to fully test itoa.
>>
>> 3 - I think it would be better to compare string and argv[i]. And
>> rather than have the user do in manually, you could use strcmp? (Yes,
>> this requires some additional work if the input has leading zeros.
>> Ignoring leading zeros was one of the few uses I found for strspn.)
>>
>Please, take a look at this version. Have I implemented
>correctly what you were referring to?
If you had tested the program, you would know the answer is no.
>#include <stdio.h>
>#include <string.h>
>#include <ctype.h>
>#include <limits.h>
>#include <stdlib.h>
>
>int atoi_function(char *string);
>void itoa_function(int n, char *string);
>void reverse(char *string);
>int equal_strings(char *string1, char *string2);
>
>int main(int argc, char **argv)
>{
> char string[1024];
> int n, m;
>
> if (argc < 2)
> {
> printf("Usage: ./program and number\n");
> return -1;
> }
>
> for (int i = 1; i < argc; i++)
> {
> n = atoi_function(argv[i]);
> itoa_function(n, string);
>
> if ((m = equal_strings(argv[i], string)) == 0)
What is the purpose of m?
> printf("\"%d\" => \"%s\"\n", n, string);
> else
> printf("Error\n");
Rather than just saying error, you could print the two values as an
aid in determining what went wrong.
> }
> return 0;
>}
>// check if the input and output strings are equal
>int equal_strings(char *string1, char *string2)
>{
> while (*string1 && (*string1 == 0))
Your mission is to explain why this while statement must always
evaluate to false.
Why didn't you test your code with input that had leading zeros?
Wasn't that one of the major purposes of this rewrite.
> string1 += 1;
> while (*string2 && (*string2 == 0))
***spoiler spacing - answer the previous comment before proceeding
I struggled with this for a while until I realized you meant
(*string1 == '0')
This is the second time in recent posts you have confused the
numerical digits with the character digits. Try to remember that 0 is
never equal to '0'.
By the way, the first half of the while statement is superfluous. If
it is true, the second half determines the result. If it is false,
the second half is not evaluated but if it were it would also be
false. Thus it is sufficient to only evaluate the second half.
> string2 += 1;
> return strcmp(string1, string2);
>}
>
>// convert string to integer
>int atoi_function(char *string)
>{
> int i, n, sign;
> //skip white space
> for (i = 0; isspace(string[i]); i++);
>
> sign = (string[i] == '-') ? -1 : 1;
> //skip sign
> if (string[i] == '+' || string[i] == '-')
> i++;
> for (n = 0; isdigit(string[i]); i++)
> n = 10 * n + (string[i] - '0');
> return sign * n;
>}
>// convert number to a character string
>// exercise 3-4, handle largest negative number
>void itoa_function(int n, char *string)
>{
> int new_n = n;
> int i, sign;
>
> i = 0;
> //generate digits in reverse order
> do
> {
> string[i++] = abs(new_n % 10) + '0';
>
> } while ((abs(new_n /= 10)) > 0);
There is no need to call abs here. It is sufficient for the updated
value of new_n to be non-zero.
>
> if ((sign = n) < 0)
> string[i++] = '-';
> string[i] = '\0';
> reverse(string);
>}
>
>void reverse(char *string)
>{
> int c;
> for (int i = 0, j = strlen(string) - 1;
> i < j; i++, j--)
> {
> c = string[i];
> string[i] = string[j];
> string[j] = c;
> }
>}
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2016-04-01 04:41 -0700 |
| Message-ID | <997214aa-a31d-4595-98be-40b9901e3d6b@googlegroups.com> |
| In reply to | #85362 |
On Wednesday, March 30, 2016 at 9:27:03 PM UTC+4, Barry Schwarz wrote:
> On Wed, 30 Mar 2016 03:41:54 -0700 (PDT), Alla _
> <modelling.data@gmail.com> wrote:
>
> >On Monday, March 28, 2016 at 10:48:35 PM UTC+4, Barry Schwarz wrote:
>
> <snip>
>
> >> There are a few issues here:
> >>
> >> 1 - Requiring the user to visually compare two ten digit values is
> >> error prone.
> >>
> >> 2 - If there is an error in your atoi function, the printout values
> >> will still match but not with the input value. It is possible that
> >> such an error could prevent itoa from processing some corner case.
> >> This would make it impossible to fully test itoa.
> >>
> >> 3 - I think it would be better to compare string and argv[i]. And
> >> rather than have the user do in manually, you could use strcmp? (Yes,
> >> this requires some additional work if the input has leading zeros.
> >> Ignoring leading zeros was one of the few uses I found for strspn.)
> >>
> >Please, take a look at this version. Have I implemented
> >correctly what you were referring to?
>
> If you had tested the program, you would know the answer is no.
>
> >#include <stdio.h>
> >#include <string.h>
> >#include <ctype.h>
> >#include <limits.h>
> >#include <stdlib.h>
> >
> >int atoi_function(char *string);
> >void itoa_function(int n, char *string);
> >void reverse(char *string);
> >int equal_strings(char *string1, char *string2);
> >
> >int main(int argc, char **argv)
> >{
> > char string[1024];
> > int n, m;
> >
> > if (argc < 2)
> > {
> > printf("Usage: ./program and number\n");
> > return -1;
> > }
> >
> > for (int i = 1; i < argc; i++)
> > {
> > n = atoi_function(argv[i]);
> > itoa_function(n, string);
> >
> > if ((m = equal_strings(argv[i], string)) == 0)
>
> What is the purpose of m?
>
> > printf("\"%d\" => \"%s\"\n", n, string);
> > else
> > printf("Error\n");
>
> Rather than just saying error, you could print the two values as an
> aid in determining what went wrong.
>
> > }
> > return 0;
> >}
> >// check if the input and output strings are equal
> >int equal_strings(char *string1, char *string2)
> >{
> > while (*string1 && (*string1 == 0))
>
> Your mission is to explain why this while statement must always
> evaluate to false.
>
> Why didn't you test your code with input that had leading zeros?
> Wasn't that one of the major purposes of this rewrite.
>
> > string1 += 1;
> > while (*string2 && (*string2 == 0))
You are right: this time I didn't check if the function
trims leading zeros; don't ask me why, I wouldn't be able
to answer - I have no idea why I have posted the code that
I didn't check! Indeed, this thing doesn't work. Honestly,
I do not see why. Here is how I interpret this code:
while (*string1 && (*string1 == 0))
For example, the argv[1] is 0023
The while loop does the following: first checks if it's not
the end of the array, i.e. checks for null terminating character;
if the condition is true, it checks if the value at the address,
to which string1 points to, is equal to zero; if yes, then
the loop moves to the next address. In case of 0023:
string[0] = 0, it's not the null terminating character *and* it is zero,
move to the next address;
string[1] = 0, it's not the null terminating character *and* it is zero,
move to the next address;
string[2] = 2, it's not the null terminating character, but it is also
not zero; loop terminates.
>
> ***spoiler spacing - answer the previous comment before proceeding
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> I struggled with this for a while until I realized you meant
> (*string1 == '0')
>
> This is the second time in recent posts you have confused the
> numerical digits with the character digits. Try to remember that 0 is
> never equal to '0'.
>
> By the way, the first half of the while statement is superfluous. If
> it is true, the second half determines the result. If it is false,
> the second half is not evaluated but if it were it would also be
> false. Thus it is sufficient to only evaluate the second half.
>
> > string2 += 1;
> > return strcmp(string1, string2);
> >}
> >
> >// convert string to integer
> >int atoi_function(char *string)
> >{
> > int i, n, sign;
> > //skip white space
> > for (i = 0; isspace(string[i]); i++);
> >
> > sign = (string[i] == '-') ? -1 : 1;
> > //skip sign
> > if (string[i] == '+' || string[i] == '-')
> > i++;
> > for (n = 0; isdigit(string[i]); i++)
> > n = 10 * n + (string[i] - '0');
> > return sign * n;
> >}
> >// convert number to a character string
> >// exercise 3-4, handle largest negative number
> >void itoa_function(int n, char *string)
> >{
> > int new_n = n;
> > int i, sign;
> >
> > i = 0;
> > //generate digits in reverse order
> > do
> > {
> > string[i++] = abs(new_n % 10) + '0';
> >
> > } while ((abs(new_n /= 10)) > 0);
>
> There is no need to call abs here. It is sufficient for the updated
> value of new_n to be non-zero.
>
> >
> > if ((sign = n) < 0)
> > string[i++] = '-';
> > string[i] = '\0';
> > reverse(string);
> >}
> >
> >void reverse(char *string)
> >{
> > int c;
> > for (int i = 0, j = strlen(string) - 1;
> > i < j; i++, j--)
> > {
> > c = string[i];
> > string[i] = string[j];
> > string[j] = c;
> > }
> >}
>
> --
> Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-04-01 13:33 +0100 |
| Message-ID | <ndlpl5$lpv$1@dont-email.me> |
| In reply to | #85554 |
On 01/04/16 12:41, Alla _ wrote: > On Wednesday, March 30, 2016 at 9:27:03 PM UTC+4, Barry Schwarz wrote: <snip> >> Your mission is to explain why this while statement must always >> evaluate to false. <snip> > while (*string1 && (*string1 == 0)) > For example, the argv[1] is 0023 > The while loop does the following: first checks if it's not > the end of the array, i.e. checks for null terminating character; > if the condition is true, it checks if the value at the address, > to which string1 points to, is equal to zero; if yes, then > the loop moves to the next address. In case of 0023: > string[0] = 0, it's not the null terminating character *and* it is zero, > move to the next address; The null terminating character has the value 0. So if a character is /not/ the null terminating character, it cannot be 0. Please give me an example of a number that is both 0 and not 0. -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web