++group((int)(value[i])/10); what does it do..? in C - c

This program is for calculating students marks frequency
float value[50];
int group[11] = {0};
for (i = 0; i < 50; i++) {
scanf("%f",&value[i]); /* reading of values */
++group[(int)(value[i])/10)]; /* what does this line do.? */
}

This line:
++group[(int)(value[i]) / 10)];
Is the same as:
int flooredValue = (int)value[i]; //e.g. 3.5 becomes 3; 12.6 becomes 12
int groupIndex = flooredValue / 10; //division discarding the remainder
group[groupIndex] += 1;
What does it mean, though? Well here's how it ends up converting the values:
value[i] | groupIndex
----------+------------
3.5 | 0
12.6 | 1
18.6 | 1
23.1 | 2
57 | 5
94.6 | 9
100 | 10
So it ends up counting how many marks fall into each bucket of 10. Scores from 0 to 9.9999 fall in the "0" bucket, from 10 to 19.99999 in the "1" bucket, etc. Note the following, though:
value[i] | groupIndex
-----------+------------
-3.5 | -3
155.6 | 15
As it is now, your input could certainly be less than zero or over 100. If that happens, you're going to write into memory outside of the bounds of group. This will lead to very unpleasant behavior. Check either that the input value is in bounds or that the group index is in bounds before indexing into the group array.

++group[(int)(value[i])/10)];
lets divide this
1. (int)(value[i])/10)
for example value[i] is 51 it will result 5 as you are using casting to int.
2. ++group[5]; // is same as group[5] += 1;
pre incrementing value of group[5]

In sub-expression
(int)(value[i])/10)
value[i] is of type float, dividing it by 10 will give double value (after default promotion). But array subscripts should be of integer type, (int) is used to cast the return value of sub-expression to integer .
In expression
++group[(int)(value[i]) / 10)];
prefix ++ is used to pre-increment the array element group[(int)(value[i])/10)].

Related

Can someone explain the logic of this bit of code?

I ran it through an IDE and the remainder values came out 3, 2, 0, 1.
I understand the first remainder, but not the rest.
Also, how come the loop terminates? Isn't x always going to be greater than 0, therefore continuing indefinitely? Thank you.
int x = 1023;
while (x > 0)
{
printf("%d", x% 10);
x = x /10;
}
Note that in C, when both operands of a division have integer type, the division also has an integer type, and the value is the result of division rounded toward zero.
So in the first iteration, the statement x = x /10; changes x from 1023 to 102 (not 102.3).
since you are dividing integers you are getting rounded results each time,
so each iteration of x becomes
102
10
1
Just print x each time and you will see.
So 102 modulo 10 is 2
10 modul0 10 is 0
1 modulo 10 is 1

Recurrence relation for the algorithm

I have already given the following algorithm which I have to find the recurrence relation.
int Recursive(int n)
{
if(n<=1)
return n;
sum=0;
for(int j=0;j<n;j++)
sum++;
return Recursive(n/2) + Recursive(n/2) + sum;
}
I have obtained recurrence relation for the above algorithm as
T(n) = 2 T(n/2) + constant
But I am not sure about the constant part of this recurrence relation since we have sum in the algorithm. Just to clarify, sum is a global variable - the lack of declaration is not a typo.
Can anyone help me out to get the correct recurrence relation? Thanks.
Assumptions made in this answer:
sum is declared globally – since the apparently missing declaration is, as you stated, not a typo.
The question asks for the return value, not the time complexity.
The expressions in the return statement are evaluated in their order of appearance; this is not guaranteed by the C standard, so the answer is technically undefined.
Note that, since each call does either:
Returns its argument (if n <= 1)
Resets the value of sum to 0
... the function is guaranteed to be "closed", in the sense that its return value will only depend on its argument. It follows that:
The two separate calls to Recursive(n / 2) can be combined into just one call, without impacting the return value: return 2 * Recursive(n / 2) + sum;.
From this point on-wards is it assumed that this modification has been applied to the original code; this helps in clarifying the flow of the program, since there will now only be one path of execution (instead of branches created by two calls).
Now for the key part. The call to Recursive(n / 2) overwrites the value of sum before the function returns, undoing the work done by the preceding for-loop. This overwriting behavior continues down the recursion hierarchy, until the final call when the stopping condition n <= 1 is hit (it just returns n instead). It follows that:
There is only one value of sum which contributes to the final return value, given by its value after the penultimate call to Recursive.
Due to truncation by integer division, when the penultimate call is performed n is always 2 or 3 (both of which satisfy n / 2 = 1); these are thus also the possible final values of sum.
What values of n give sum = 2 and sum = 3 respectively? It is illustrative to consider the binary representation of n.
Integer division by 2 is equivalent to shifting the bit-pattern "right" by 1 (or "left" depending on endian-ness...), and discarding the least-significant bit. It follows that the final value of sum depends on only the 2 most significant bits of n:
initial bit-pattern >> penultimate call
-----------------------------------------
...000 10 xxx... ...0000 10 = 2
...000 11 xxx... ...0000 11 = 3
xxx: discarded bits
The bit-pattern of n has floor(log2(n)) + 1 significant bits; the final value of sum can therefore be compactly expressed as:
S(n) = 2 + second_most_significant_bit(n)
How many times is sum added to the return value? The number of recursive calls to Recursive (i.e. the total number of calls minus one, including the initial call, but excluding the final). This is given by floor(log2(n)):
Note that the return value of the final call will always be 1 if initially n >= 1. Therefore the final return value of Recursive is given by:
Test C code for confirmation:
// override the library definition of log2 to use integers only
int log2(int n) {
int b = 0;
while ((n >>= 1) != 0)
b++;
return b;
}
// get i-th bit from bit pattern of n
int get_bit(int n, int i) {
return (n >> (i - 1)) & 1;
}
// calculating return value of Recursive using equation above
int Value(int n) {
int l2n = log2(n); // floor(log2(n))
int p2l = 1 << l2n; // 2^(floor(log2(n)))
return p2l + (p2l - 1) * (2 + get_bit(n, l2n));
}
Results:
n | Recursive Value
-------------------------------
2 | 4 4
3 | 5 5
4 - 5 | 10 10
6 - 7 | 13 13
8 - 11 | 22 22
12 - 15 | 29 29
16 - 23 | 46 46
24 - 31 | 61 61
32 - 47 | 94 94
48 - 63 | 125 125
64 - 95 | 190 190
I am not sure about the constant part of this recurrence relation
There is no constant part, since sum equals n after the loop. This gives:
T(n) = 2T(n/2)+n
So if the sum is global variable, T(n) = 2T(n/2)+C(Constant) and if sum is local variable T(n) = 2T(n/2)+n . Am I correct?
No, as mch wrote:
It seems that sum is a global variable… In this case it would be unspecified if sum or one of the Recursive(n/2) will be evaluated first.
This means it would be unspecified whether T(n) = 2T(n/2)+n or T(n) = 2T(n/2)+n/2; in neither case there's a constant part.

How do I manipulate the digits of a number?

In some kinds of problems I often face this situation where I have a variable where I need to rearrange the digits, e.g., int e = 2385;. Let's suppose I don't know which number is stored there, but still I need to shift 2nd and 4th position. When I know variable's value I can simply do e = 2583, but when I don't know I simply can't solve the problem.
Another situation is when I have two values and want to use them to form another number i.e int a = 2, b = 1;, and I need to order them so that I will get a 21 or a 212. I mean, that's easy to do when I'm outputting data, I can simply do:
printf("%d%d\n",a,b);
printf("%d%d%d",a,b,a);
Problem is when I have to store this number in another variable. I don't know how to do that.
This can be broken into two tasks: (1) breaking up a number into pieces, and (2) combining pieces into a whole number.
To break up a number into pieces, use the division and modulus operators.
int num = 2385;
int a = num / 1000; // 2
int b = num / 100 % 10; // 3
int c = num / 10 % 10; // 8
int d = num / 1 % 10; // 5
The trick is to use division to remove the digits to the right, then modulus to keep only the rightmost digit. For example, to calculate the hundreds' place (b) we compute 2385 / 100, which is 23. 23 % 10 is the remainder when you divide 23 by 10. The remainder is 3.
To combine the pieces back into a number, do the opposite with multiplication and addition.
num = a * 1000 // 2000
+ d * 100 // + 500
+ c * 10 // + 80
+ b * 1; // + 3
// ----
// 2583
Notice how I switched d and b to swap those digits.

what does this will do in C programing: ++group[ (int) (value[i]+0.5)/10]

Following code is example of how to confirm if number entered is in specific range or not.
For example if I enter number say N then I want increment counter which says if it is in range of:
1-10
11-20
...
91-100
Here is the code snip from one of the text book:
#define MAXVAL 50
#define COUNTER 11
main ()
{
float value[MAXVAL];
int i, low, high;
static group[COUNTER] = {0,0,0,0,0,0,0,0,0,0,0}
*/READING AND COUNTING*/
for(i=0; i<MAXVAL; i++)
{
/* READING OF VALUES*/
scanf("%f", &value[i]);
/* COUNTING FREQUENCY OF GROUPS */
++group[ (int) (value[i]+0.5)/10] <<< I would like to understand how this will find if number is in specific ranges?
/* PRINTING OF FREQUENCY TABLE */
printf("\n");
printf(" GROUP RANGE FREQUENCY\N\N");
for(i=0; i< COUNTER; i++)
{
low = i*10;
if (i==10)
high =100;
else
high=low + 9;
printf( " %2d %3dto%3d %d)\n", i+1, low,high,group[i]);
}
}
What does this will do in above C program: ++group[ (int) (value[i]+0.5)/10]
Thanks
Examine the index of the group array:
[(int) (value[i]+0.5)/10]
This effectively takes the value scanned in from console input, adds .50, divide the sum by 10, then convert to an int. The better question is why do this at all?
The addition of 0.50 is to account for rounding. If value[i] is at or above a marign of 0.50 (such as 1.51, 2.50, 3.99, etc) this forces it to the next whole number (2.01, 3.00, 4.49).
Next, the division by 10. This apparently assumes the values being input are between 0.00 and exclusively less than 109.50. Dividing by 10 ensures these values will be between 0.00 and 10.00. This will, of course not work as soon as the console input is greater than 109.50.
Then the cast to (int). Straight forward enough. Kill the fraction off the float and manufacture your int.
Finally, assuming the input was in fact between 0.00 and exclusively less than 109.50, the counter matching the requisite range in the group[] array will be incremented by one.
Bottom line, it is a poor mechanism for trying to cluster input values into groups and updating counters within he appropriate range, and it will choke as soon as the input value is > 109.50.
Lets break it down for understanding it.
read ++group[ (int) (value[i]+0.5)/10] as:
I want to increment the index of group array by 1.
Which index?
It somehow depends on the value entered by user (value[i])
Why add 0.5 to it?
To round a floating number. more specifically to take the ceil() of that number
Why divide by 10?
Because your groups are of size 10.
Example:
User enters 11.
value[i] = 11 (float)
11 + 0.5 = 11.5 (float)
11.5 / 10 = 1.15 (float)
typecast 1.15 to int = 1 (int)
++group[1], increments group[1] by 1 and shows that 11 falls in group 1 i.e. 10 - 19
Another example:
User enters 9.
value[i] = 9 (float)
9 + 0.5 = 9.5 (float)
9.5 / 10 = 0.95 (float)
typecast 0.95 to int = 0 (int)
++group[0], increments group[0] by 1 and shows that 9 falls in group 0 i.e. 0 - 9
Another example:
User enters 9.1.
value[i] = 9.1 (float)
9.1 + 0.5 = 9.6 (float)
9.6 / 10 = 0.96 (float)
typecast 0.95 to int = 1 (int)
++group[1], increments group[1] by 1 and shows that 9.1 falls in group 1 i.e. 10 - 19
Note:
According to the code, your groups are 0-9, 10 - 19 ... and not 1 - 10, 11 - 20
um something like this:
Assuming group[0] = 0->10, group[1] = 11->20, group[2] = 21->30..
take an example float: 10.3
Applying the formula there, 10.8/10 ~= 1. Hence its in the range 10->20.
Take another example: 22.4
Applying the formula there, (22.4 + 0.5)/10 ~= 22.9/10 = 2. Hence its in the range 20->30. And so on. It will work for high = 100 and low = 0.
++group[ (int) (value[i]+0.5)/10] is
taking the float input value value[i],
rounding it to an int (int) (value[i]+0.5)
then dividing it by 10 to get a group index, and then
adding 1 ++group[...] to the group it belongs to.
In other words it is computing the number of values that fall between 0..9, 10..19, 20..29, ... 100..109, 110..119
This code is completely unsafe. If the input value is greater that than COUNTER * 10 or negative, then random bytes of memory will be written. Throw this code away or place some safety checks into it.
EDIT
Safety check, ignore input values that are out of range.
int g = (int) (value[i]+0.5) /10]
if (0 <= g && g < COUNT)
++group[g];

Octal to Decimal multidigit in C

I have a program I am writing that converts Octal to Decimal numbers. Most of it works.
(more code above this, assume all variables are properly declared).
for(i; i > 0; i--)
{
decimalNumber = (decimalNumber + (number['i'] * pow(8,power)));
power++;
}
The code correctly shifts over to the right to do other digits but it doesn't change the number it is working with. For example, entering 54 in octal results in an output of 36, 4*(8^0) + 4*(8^1) when it should be outputting 4*(8^0) + 5*(8^1), or 44.
'i' is a constant. You probably meant just i. Also, << 3.
As Ignacio pointed out, 'i' is a constant and will cause you to access the same out of bounds array element on each iteration of the loop. Since I assume you start with i equal to the number of digits in the array (you didn't show that code), you want to subtract 1 from it when you use it as an array index.
You're traversing the string in the wrong direction.
Or, better, change your logic:
5 -> 5*8^0
54 -> (5*8^0)*8 + 4
543 -> ((5*8^0)*8 + 4)*8 + 3
number[0] is 5
number[1] is 4
decimalNumber is 0
power is 0
i = 1 downto 0 do
decimalNumber = (decimalNumber + (number[i:1,0] * pow(8,power:0,1)));
power++;
do end

Resources