Garbage produced

V

Vikram

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));
}
 
I

Ian Collins

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);

This won't do what you expect (it will give you the size of an int*),
you have to pass in the size.
 
B

Bartc

Fred said:
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?
 
V

Vikram

Ian said:
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.
This won't do what you expect (it will give you the size of an int*),
you have to pass in the size.

Kind Regards,
Vikram
 
D

David Resnick

Ian said:
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.
This won't do what you expect (it will give you the size of an int*),
you have to pass in the size.

Try as an experiment doing a printf of the result of sizeof the
argument, and you will discover Ian is correct...

-David
 
W

Willem

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.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
B

Bartc

Keith said:
Bartc said:
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?

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

Willem

Vikram wrote:
)>> float mean(int x[])
)
) ^^^^^^^
)
) NB in this function I am considering the pointer, as an array.

You're not. You only think you are. That's not how C works.
In C, the above is exactly 100% equivalent to
float mean(int *x)

HTH, HAND.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

James Lothian

Vikram said:
Ian said:
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.
There is no sensible way for the function to know the size
of the array it's been passed, unless you tell it:

float mean(int *x, int count)
{
int i;
float sum = 0.0;
for(i = 0; i < count; sum += x[i++])
;
return sum/count;
}

main()
{
int* x,n;
int count = 0;
printf("how many numbers? ");
scanf("%d",&n);
count = n;
x=malloc(n*sizeof(int));
printf("enter %d numbers\n",n);
while(n--)
scanf("%d",x+n);
printf("mean=%f\n",mean(x, count));
}

(untested code, no warranty &c)
James
 
P

Paul N

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.

Hope this is of use to someone.
Paul.
 
F

Fred

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?
 
D

Dann Corbit

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.
 
K

Keith Thompson

Bartc said:
Fred said:
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.
 
K

Keith Thompson

Bartc said:
Keith said:
Bartc said:
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.
 
V

Vikram

James said:
Vikram said:
Ian said:
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
 
D

Dann Corbit

James said:
Vikram said:
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.

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
Copyright (C) Microsoft Corporation. All rights reserved.

t.c
Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.

/out:t.exe
t.obj

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

Hans Vlems

James said:
Vikram said:
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
 
K

Keith Thompson

Vikram said:
James said:
Vikram said:
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.

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.
 
K

Kenny McCormack

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);
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top