Velocity Reviews > Garbage produced

# Garbage produced

Fred
Guest
Posts: n/a

 01-24-2011
On Jan 24, 2:05*pm, Paul N <(E-Mail Removed)> wrote:
> On Jan 24, 9:28*pm, Willem <(E-Mail Removed)> wrote:
>
>
>
>
>
> > Vikram wrote:

>
> > ) the code below will find the mean (average) of some numbers, however it
> > ) produces only garbage. Can you see a problem?
> > )
> > ) float mean(int x[])
> > ) {
> > ) * int i,n;
> > ) * float sum;
> > ) * n=sizeof(x);
> > ) * for(i=sum=0;i<n;sum+=x[i++]);
> > ) * return sum/n;
> > ) }

>
> > That's not how arrays work in C. *They don't know how big they are.
> > sizeof() is not meant to find out the number of elements in an array.

>
> I beg to differ. sizeof can be used to find the number of elements in
> an array. The reasons it's not working here are:
>
> a) The x in main isn't an array, it's a pointer set using malloc;
> b) Even if it was, it gets turned into a pointer when you pass it to a
> function, so the x in mean is a pointer, and would be even if the x in
> main was an array;
> c) If x was an array of int, you would need to divide sizeof(x) by
> sizeof(int) to get the number of elements.
>

There is a second problem with the code not related to array vs.
pointer.

for(i=sum=0;i<n;sum+=x[i++]);
return sum/n;

The above is not a safe way to find the mean of a set of floats.
Consider:
x[0] = FLT_MAX;
x[1] = FLT_MAX / 2.;
What is the mean, and what would the above code return?
--
Fred K

Keith Thompson
Guest
Posts: n/a

 01-24-2011
Vikram <(E-Mail Removed)> writes:
> Ian Collins writes:
>> On 01/25/11 09:50 AM, Vikram wrote:
>>> Hello friends
>>>
>>> the code below will find the mean (average) of some numbers, however it
>>> produces only garbage. Can you see a problem?
>>>
>>> Kind Regards,
>>> Vikram
>>>
>>>
>>> float mean(int x[])

>
> ^^^^^^^
>
> NB in this function I am considering the pointer, as an array.

[...]

Read section 6 of the comp.lang.c FAQ, <http://www.c-faq.com/>.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Dann Corbit
Guest
Posts: n/a

 01-24-2011
In article <6317e052-c51c-4d7a-88ee-dfce5b2b23d0
>
> On Jan 24, 2:05*pm, Paul N <(E-Mail Removed)> wrote:
> > On Jan 24, 9:28*pm, Willem <(E-Mail Removed)> wrote:
> >
> >
> >
> >
> >
> > > Vikram wrote:

> >
> > > ) the code below will find the mean (average) of some numbers, however it
> > > ) produces only garbage. Can you see a problem?
> > > )
> > > ) float mean(int x[])
> > > ) {
> > > ) * int i,n;
> > > ) * float sum;
> > > ) * n=sizeof(x);
> > > ) * for(i=sum=0;i<n;sum+=x[i++]);
> > > ) * return sum/n;
> > > ) }

> >
> > > That's not how arrays work in C. *They don't know how big they are.
> > > sizeof() is not meant to find out the number of elements in an array.

> >
> > I beg to differ. sizeof can be used to find the number of elements in
> > an array. The reasons it's not working here are:
> >
> > a) The x in main isn't an array, it's a pointer set using malloc;
> > b) Even if it was, it gets turned into a pointer when you pass it to a
> > function, so the x in mean is a pointer, and would be even if the x in
> > main was an array;
> > c) If x was an array of int, you would need to divide sizeof(x) by
> > sizeof(int) to get the number of elements.
> >

>
> There is a second problem with the code not related to array vs.
> pointer.
>
> for(i=sum=0;i<n;sum+=x[i++]);
> return sum/n;
>
> The above is not a safe way to find the mean of a set of floats.
> Consider:
> x[0] = FLT_MAX;
> x[1] = FLT_MAX / 2.;
> What is the mean, and what would the above code return?

That is easily repaired by making sum a double (assuming that double is
larger than float).

Welford's accumulation and/or Kahan's accumulation could also prove
useful.

His biggest issue is failure to read c-faq section 6. For instance:

6.21:Why doesn't sizeof properly report the size of an array when the
array is a parameter to a function?

A: The compiler pretends that the array parameter was declared as a
pointer (see question 6.4), and sizeof reports the size of the
pointer.

References: H&S Sec. 7.5.2 p. 195.

Keith Thompson
Guest
Posts: n/a

 01-25-2011
"Bartc" <(E-Mail Removed)> writes:
> Fred wrote:
>> There is a second problem with the code not related to array vs.
>> pointer.
>>
>> for(i=sum=0;i<n;sum+=x[i++]);
>> return sum/n;
>>
>> The above is not a safe way to find the mean of a set of floats.
>> Consider:
>> x[0] = FLT_MAX;
>> x[1] = FLT_MAX / 2.;
>> What is the mean, and what would the above code return?

>
> Are values near FLT_MAX really likely? If so, then it makes it pretty much
> impossible to do any sort of floating point arithmetic.
>
> A typical value of FLT_MAX is some 10**38. If values are limited to, say, a
> billion billion billion (which should cover a lot of applications unless
> silly units are being used), you need to add 10 billion such maximums before
> you get overflow.
>
> And that assumes you can't use double for some reason, if the numbers are
> going to be big, which typically has a maximum of 10**300 or so.
>
> Anyway, how *would* you calculate the average of lots of numbers near to
> FLT_MAX?

One solution is to divide *each* number by n, them sum the quotients.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Keith Thompson
Guest
Posts: n/a

 01-25-2011
"Bartc" <(E-Mail Removed)> writes:
> Keith Thompson wrote:
>> "Bartc" <(E-Mail Removed)> writes:
>>> Fred wrote:

>
>>>> for(i=sum=0;i<n;sum+=x[i++]);
>>>> return sum/n;
>>>>
>>>> The above is not a safe way to find the mean of a set of floats.
>>>> Consider:
>>>> x[0] = FLT_MAX;
>>>> x[1] = FLT_MAX / 2.;
>>>> What is the mean, and what would the above code return?
>>>
>>> Are values near FLT_MAX really likely? If so, then it makes it
>>> pretty much impossible to do any sort of floating point arithmetic.

>
>>> Anyway, how *would* you calculate the average of lots of numbers
>>> near to FLT_MAX?

>>
>> One solution is to divide *each* number by n, them sum the quotients.

>
> Doesn't that just move the problem elsewhere? Suppose the numbers are near
> FLT_MIN?

If only some of them are near FLT_MIN (or -FLT_MIN), there's no problem.
If all of them are, then yes, you could lose information (though it
won't overflow).

> And isn't this likely to lose accuracy (it would do with integers)?

Barring very small numbers, I don't think so.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Vikram
Guest
Posts: n/a

 01-25-2011
James Lothian writes:
> Vikram wrote:
>> Ian Collins writes:
>>
>>> On 01/25/11 09:50 AM, Vikram wrote:
>>>> Hello friends
>>>>
>>>> the code below will find the mean (average) of some numbers, however
>>>> it produces only garbage. Can you see a problem?
>>>>
>>>> Kind Regards,
>>>> Vikram
>>>>
>>>>
>>>> float mean(int x[])

>>
>> ^^^^^^^
>>
>> NB in this function I am considering the pointer, as an array.

>
> Regardless of how you like to think about it, when you pass an array to
> a function in C, the function receives a pointer to the first element of
> the array. That's just the way passing an array works in C. If you take
> sizeof() the parameter, you'll just get the size of the pointer, which
> is nothing to do with the size of the array.

Hello James

discovered is my library's sizeof() function is buggy! For some reason it
miscalculates all sizes by a multiple of 4. It's easy to correct this,
see the code below

#define sizeof(x) (sizeof(x)/4)
main()
{
int a1[1];
int a2[5];
int a3[20];
printf("1=%d\n5=%d\n20=%d\n",sizeof(a1),sizeof(a2) ,sizeof(a3));
return(0);
}

This now successfully produces:
1=1
5=5
20=20

Kind Regards,
Vikram

Dann Corbit
Guest
Posts: n/a

 01-25-2011
In article <ihn8i3\$tqj\$(E-Mail Removed)>, (E-Mail Removed)lid
says...
>
> James Lothian writes:
> > Vikram wrote:
> >> Ian Collins writes:
> >>
> >>> On 01/25/11 09:50 AM, Vikram wrote:
> >>>> Hello friends
> >>>>
> >>>> the code below will find the mean (average) of some numbers, however
> >>>> it produces only garbage. Can you see a problem?
> >>>>
> >>>> Kind Regards,
> >>>> Vikram
> >>>>
> >>>>
> >>>> float mean(int x[])
> >>
> >> ^^^^^^^
> >>
> >> NB in this function I am considering the pointer, as an array.

> >
> > Regardless of how you like to think about it, when you pass an array to
> > a function in C, the function receives a pointer to the first element of
> > the array. That's just the way passing an array works in C. If you take
> > sizeof() the parameter, you'll just get the size of the pointer, which
> > is nothing to do with the size of the array.

>
> Hello James
>

He is not wrong. You are failing to understand what he told you.

> I have been doing some tests and what I
> discovered is my library's sizeof() function is buggy!

It is your understanding that is buggy.

> For some reason it
> miscalculates all sizes by a multiple of 4. It's easy to correct this,
> see the code below

Surely, you are a troll.

> #define sizeof(x) (sizeof(x)/4)
> main()
> {
> int a1[1];
> int a2[5];
> int a3[20];
> printf("1=%d\n5=%d\n20=%d\n",sizeof(a1),sizeof(a2) ,sizeof(a3));
> return(0);
> }
>
> This now successfully produces:
> 1=1
> 5=5
> 20=20
>
> Kind Regards,

C:\tmp>type t.c
#include <stdio.h>

int main(void)
{
int a1[1];
int a2[5];
int a3[20];
printf("1=%d\n5=%d\n20=%d\n", sizeof a1 / sizeof a1[0], sizeof a2 /
sizeof a2[0], sizeof a3 / sizeof a3[0]);
printf("1=%d\n5=%d\n20=%d\n", sizeof a1 / sizeof(int), sizeof a2 /
sizeof(int), sizeof a3 / sizeof(int));

return 0;
}

C:\tmp>cl t.c
Microsoft (R) C/C++ Optimizing Compiler Version 16.00.30319.01 for x64

t.c
Microsoft (R) Incremental Linker Version 10.00.30319.01

/out:t.exe
t.obj

C:\tmp>t
1=1
5=5
20=20
1=1
5=5
20=20

Hans Vlems
Guest
Posts: n/a

 01-25-2011
On 25 jan, 20:33, Vikram <(E-Mail Removed)> wrote:
> James Lothian writes:
> > Vikram wrote:
> >> Ian Collins writes:

>
> >>> On 01/25/11 09:50 AM, Vikram wrote:
> >>>> Hello friends

>
> >>>> the code below will find the mean (average) of some numbers, however
> >>>> it produces only garbage. Can you see a problem?

>
> >>>> Kind Regards,
> >>>> Vikram

>
> >>>> float mean(int x[])

>
> >> * * * * * * * *^^^^^^^

>
> >> NB in this function I am considering the pointer, as an array.

>
> > Regardless of how you like to think about it, when you pass an array to
> > a function in C, the function receives a pointer to the first element of
> > the array. That's just the way passing an array works in C. If you take
> > sizeof() the parameter, you'll just get the size of the pointer, which
> > is nothing to do with the size of the array.

>
> Hello James
>
> I think you are wrong about this. I have been doing some tests and what I
> discovered is my library's sizeof() function is buggy! For some reason it
> miscalculates all sizes by a multiple of 4. It's easy to correct this,
> see the code below
>
> #define sizeof(x) (sizeof(x)/4)
> main()
> {
> * int a1[1];
> * int a2[5];
> * int a3[20];
> * printf("1=%d\n5=%d\n20=%d\n",sizeof(a1),sizeof(a2) ,sizeof(a3));
> * return(0);
>
> }
>
> This now successfully produces:
> 1=1
> 5=5
> 20=20
>
> Kind Regards,
> Vikram

When a poster breathlesly informs this newsgroup that he/she has found
a bug in a compiler or its supporting components more ofthen than not
it proves to be a hole in his/her knowledge.
Don't take this personal, it's a fact of life.
Hans
BTW the little program seems to prove that your compiler's sizeof() is
quite alright

Keith Thompson
Guest
Posts: n/a

 01-25-2011
Vikram <(E-Mail Removed)> writes:
> James Lothian writes:
>> Vikram wrote:
>>> Ian Collins writes:
>>>
>>>> On 01/25/11 09:50 AM, Vikram wrote:
>>>>> Hello friends
>>>>>
>>>>> the code below will find the mean (average) of some numbers, however
>>>>> it produces only garbage. Can you see a problem?
>>>>>
>>>>> Kind Regards,
>>>>> Vikram
>>>>>
>>>>>
>>>>> float mean(int x[])
>>>
>>> ^^^^^^^
>>>
>>> NB in this function I am considering the pointer, as an array.

>>
>> Regardless of how you like to think about it, when you pass an array to
>> a function in C, the function receives a pointer to the first element of
>> the array. That's just the way passing an array works in C. If you take
>> sizeof() the parameter, you'll just get the size of the pointer, which
>> is nothing to do with the size of the array.

>
> Hello James
>
> I think you are wrong about this. I have been doing some tests and what I
> discovered is my library's sizeof() function is buggy! For some reason it
> miscalculates all sizes by a multiple of 4. It's easy to correct this,
> see the code below

You have misunderstood.

> #define sizeof(x) (sizeof(x)/4)

This macro is likely to break things very badly if you try to use it.

> main()

This should be "int main(void)". Your compiler will probably let you
get away with the old-style "main()" declaration. This is not the cause
of your problems, but you should fix it anyway.

> {
> int a1[1];
> int a2[5];
> int a3[20];
> printf("1=%d\n5=%d\n20=%d\n",sizeof(a1),sizeof(a2) ,sizeof(a3));

sizeof (either the built-in operator or your macro) yields a result of
type size_t, which is an unsigned type. The "%d" format requires an
argument of type int, a signed type. If size_t and int happen to be the
same size on your system, the above is likely to *appear* to work
correctly, but it could break badly on a different system. You can
avoid this by converting each operand to int, or (if your implementation
supports it), by using the "%zu" format which does require a size_t
argument.

printf("1=%d\n5=%d\n20=%d\n", (int)sizeof a1, (int)sizeof a2, (int)sizeof a3);
or
printf("1=%zu\n5=%zu\n20=%zu\n", sizeof a1, sizeof a2, sizeof a3);

This is not the cause of your problems, but you should fix it anyway.

> return(0);

The parentheses are unnecessary but harmless.

> }
>
> This now successfully produces:
> 1=1
> 5=5
> 20=20

That's the output I'd expect on a system with sizeof(int) == 4.

Some things you should understand:

sizeof is an operator, not a function. It might seem odd to have an
operator whose name is a keyword rather than a sequence of one or more
punctuation characters, but there it is.

There are actually two forms. One is ``sizeof expr'', which
yields the size of the result of an expression (without evaluating
the operand in most cases). If you write ``sizeof(a1)'', you're
applying sizeof to a parenthesized expression; the parentheses
are part of the operand, not part of the syntax of sizeof itself,
just like writing ``-(x)'' rather than ``-x''. If you're more
comfortable adding parentheses, they won't hurt anything (the same
applies to your return statement), but you should at least be able to
understand what's going on when you're reading someone else's code.
In some cases you might need parentheses just for grouping.

The other form is ``sizeof ( type-name )'', which yields the size
of a given type; for that form, the parentheses are required.

sizeof yields the size of its operand *in bytes*. It does not yield the
number of elements in an array, unless the array happens to have
one-byte elements. (A byte is *at least* 8 bits; it will be exactly
8 bits on any system you're likely to encounter.)

The reason dividing by 4 gave results that you thought were sensible is
that sizeof(int) happens to be 4 on your system. It could be 2, or 8,
or even 1, on another system (the latter is possible only if a byte is
at least 16 bits).

It's common to define a macro to determine the number of elements in an
array:

#define ARRAY_LENGTH(arr) (sizeof (arr) / sizeof (arr[0]))

Note that this works only if you apply it to an array object. If you
try to apply it to a function parameter -- well, read section 6 of
the comp.lang.c FAQ, <http://www.c-faq.com/>. And browse the rest of it
while you're there; it's an excellent resource.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Kenny McCormack
Guest
Posts: n/a

 01-25-2011
In article <ihkomc\$ehm\$(E-Mail Removed)>,
Vikram <(E-Mail Removed)> wrote:
>Hello friends
>
>the code below will find the mean (average) of some numbers, however it
>produces only garbage. Can you see a problem?
>
>Kind Regards,
>Vikram
>
>
>float mean(int x[])
>{
> int i,n;
> float sum;
> n=sizeof(x);
> for(i=sum=0;i<n;sum+=x[i++]);
> return sum/n;
>}
>
>main()
>{
> int* x,n;
> printf("how many numbers? ");
> scanf("%d",&n);
> x=malloc(n*sizeof(int));
> printf("enter %d numbers\n",n);
> while(n--)scanf("%d",x+n);
> printf("mean=%f\n",mean(x));
>}

Isn't it funny how everybody has posted all this irrelevant stuff about
sizeof, and pointers, and arrays, and what have you, but nobody has
actually told you how to fix your program?

Here's how it should be written:

/* First, the usual garbage to get past the CLC censors */
#include <stdio.h>
int main(void)
{
int *x,i,n;
double sum;

printf("how many numbers? ");
scanf("%d",&n);
x=malloc(n*sizeof(int));
printf("enter %d numbers\n",n);
while(n--)scanf("%d",x+n);
for(i=sum=0;i<n;sum+=x[i++]);
printf("mean=%f\n",sum/n);
}

--
"We should always be disposed to believe that which appears to us to be
white is really black, if the hierarchy of the church so decides."

- Saint Ignatius Loyola (1491-1556) Founder of the Jesuit Order -