mixing types promotion etc..

S

Stef

Hello

I have been programming C now for a couple of months but at this
moment I am a bit confused with types like double float etc..

My question wat type does the result have when a double value is mixed
with an int... In the snippet below I substract a double with an int
but the results are.. unpredictable for me.

Can I mix ints with doubles doing floating point calculations ?

#include <stdio.h>

int main(int argc, char *argv[]) {
double C, M, Y;
int R, G, B;

C = M = Y = 0;

R = 128;
G = 211;
B = 87;

printf("type is INT: red:%d, green:%d, blue:%d\n", R, G, B);

printf("type is DOUBLE: red:%g, green:%g, blue:%g\n",
(double)R / 255, (double)G / 255, (double)B / 255);

C = 1.0 - (R / 255);
M = 1.0 - (G / 255);
Y = 1.0 - (B / 255);

printf("ONE - C: %g, M: %g, Y: %g\n", C, M, Y);
printf("TWO - C: %g, M: %g, Y: %g\n", (double)C, (double)M,
(double)Y);
printf("THREE - C: %g, M: %g, Y: %g\n",
(1.0 - (R / 255)), (1.0 - (G / 255)), (1.0 - (Y / 255)));
printf("FOUR - C: %g, M: %g, Y: %g\n",
(double)(1.0 - (R / 255)), (double)(1.0 - (G / 255)), (double)(1.0
- (Y / 255)));

return 0;
}
 
J

Jens.Toerring

Stef said:
I have been programming C now for a couple of months but at this
moment I am a bit confused with types like double float etc..
My question wat type does the result have when a double value is mixed
with an int... In the snippet below I substract a double with an int
but the results are.. unpredictable for me.
Can I mix ints with doubles doing floating point calculations ?

Yes, you can - you just have to figure out what makes something a
double and what an int;-)
#include <stdio.h>
int main(int argc, char *argv[]) {
double C, M, Y;
int R, G, B;
C = M = Y = 0;
R = 128;
G = 211;
B = 87;
printf("type is INT: red:%d, green:%d, blue:%d\n", R, G, B);
printf("type is DOUBLE: red:%g, green:%g, blue:%g\n",
(double)R / 255, (double)G / 255, (double)B / 255);

Here you force 'R' etc. to be converted to a double before
the division is done, so it probably does what you expect.
C = 1.0 - (R / 255);
M = 1.0 - (G / 255);
Y = 1.0 - (B / 255);

I guess you have trouble with these line since 'C', 'M' and 'Y'
are always 1.0 or 0.0. The problem is that e.g. in

R / 255

both 'R' and 255 are integers, so the division is an "integer
division", which results in another integer with the decimal
part of the result truncated. And since 'R' is probably never
larger than 255 you get for all values (except for R == 255)
a result of 1.0 (and 0.0 for R == 255).

Only after that calculation (for which you don't even need
parentheses since division has a higher "precedence" than
addition or subtraction) the result is converted to a double
since the other operand of the subtraction is a double.

If you want some probably more useful results you should write
instead

C = 1 - R / 255.0;

Now 'R' gets converted to a double before the division is done
since the other operand is a double. As you will note you can
use the integer 1 instead of a double here for the subtraction
bcause now the result of the division is already a double and
the 1 will then get converted automatically to a double.
printf("ONE - C: %g, M: %g, Y: %g\n", C, M, Y);
printf("TWO - C: %g, M: %g, Y: %g\n", (double)C, (double)M,
(double)Y);
printf("THREE - C: %g, M: %g, Y: %g\n",
(1.0 - (R / 255)), (1.0 - (G / 255)), (1.0 - (Y / 255)));

Shouldn't you have 'C' instead of 'R' and 'M' instead of 'G' in the
second and third argument to printf()?
printf("FOUR - C: %g, M: %g, Y: %g\n",
(double)(1.0 - (R / 255)), (double)(1.0 - (G / 255)), (double)(1.0
- (Y / 255)));

And here again? Perhaps that contributes to the confusion...

Regards, Jens
 
J

Jens.Toerring

I guess you have trouble with these line since 'C', 'M' and 'Y'
are always 1.0 or 0.0. The problem is that e.g. in
both 'R' and 255 are integers, so the division is an "integer
division", which results in another integer with the decimal
part of the result truncated. And since 'R' is probably never
larger than 255 you get for all values (except for R == 255)
a result of 1.0 (and 0.0 for R == 255).

Make that "a result of 0 (and 1 for R = 255)." Sorry, got that
confused with the final result of the complete expression.

Regards, Jens
 
E

Eric Sosman

Stef said:
Hello

I have been programming C now for a couple of months but at this
moment I am a bit confused with types like double float etc..

My question wat type does the result have when a double value is mixed
with an int... In the snippet below I substract a double with an int
but the results are.. unpredictable for me.

Can I mix ints with doubles doing floating point calculations ?

Yes. When an arithmetic operator like `+' has
a double and an int as operands, the int is converted
to double and then the result is computed in double
arithmetic. However, this conversion happens on an
operand-by-operand basis, not just once for an entire
expression involving several operators, and this is
probably what's confusing you. See below.
#include <stdio.h>

int main(int argc, char *argv[]) {
double C, M, Y;
int R, G, B;

C = M = Y = 0;

R = 128;
G = 211;
B = 87;

printf("type is INT: red:%d, green:%d, blue:%d\n", R, G, B);

printf("type is DOUBLE: red:%g, green:%g, blue:%g\n",
(double)R / 255, (double)G / 255, (double)B / 255);

This is fine, and presumably you got the expected results.
Since the three expressions are identical in form, I'll just
analyze the first one: `(double)R / 255'.

`(double)' is an operator that takes one operand, in this
case the int value of `R'. The effect is to produce a double
value equivalent to R's int value, and that converted value
becomes the numerator of the fraction.

Next comes the `/' operator. Its two operands are a double
(the converted R) and an int (255). The effect is to convert
the 255 from int to double (255.0) and then to divide the two
double quantities, yielding a double result just a little
larger than one-half.
C = 1.0 - (R / 255);
M = 1.0 - (G / 255);
Y = 1.0 - (B / 255);
printf("ONE - C: %g, M: %g, Y: %g\n", C, M, Y);

This is presumably what confuses you, and here's where
the "operand-by-operand" conversion makes a difference. Again,
I'll just analyze the first expression.

First comes the division, whose operands are `R' and `255'.
Both of these values have int type, so no conversion to a
common type is needed: the program performs an integer division
and yields an integer result. Integers have no fractional parts,
so the result has no fractional part: R / 255 yields zero, with
a largish remainder that's discarded.

Next comes the subtraction, whose operands are `1.0' and
the result of the division. That result is an int, so it's
converted to a double, yielding 0.0. Then the subtraction
happens as 1.0 - 0.0, yielding 1.0.
printf("TWO - C: %g, M: %g, Y: %g\n", (double)C, (double)M,
(double)Y);

Since C, M, and Y are already of type double, converting
them with `(double)' operators does precisely nothing. You
should get the same values as before.
printf("THREE - C: %g, M: %g, Y: %g\n",
(1.0 - (R / 255)), (1.0 - (G / 255)), (1.0 - (Y / 255)));

The first two of these work just as they did when you
computed C,M,Y above, and should give the same answers. The
last is different, since `Y' is a double. Let's work through
`1.0 - (Y / 255)':

First, the division: the numerator is the double `Y' and
the denominator is the `int' 255. The 255 is converted to
255.0, and then the division occurs, yielding a quotient of
about 0.004. Then comes the subtraction; both operands are
double so no conversion is necessary, and the difference
comes out to roughly 0.996.
printf("FOUR - C: %g, M: %g, Y: %g\n",
(double)(1.0 - (R / 255)), (double)(1.0 - (G / 255)), (double)(1.0
- (Y / 255)));

This is just like the preceding statement. Since each of
`1.0 - (x / 255)' produces a double result, applying the `(double)'
operator to it does nothing at all and you should get the same
result as before.

The thing to remember is that each operator takes care of
whatever conversions its own operands needs, but does so the
same way whether it's standing on its own or is part of a
larger expression. In `C = 1.0 - (R / 255)' the `/' operator
has a pair of int operands and performs an integer division;
the fact that the result will later be converted from int to
double doesn't change anything. If you want to do a double
division so you can retain the fractional part, you must cause
the operands to be converted to double before the division
takes place. Here are some rewrites (I've dropped the parens
because they're unnecessary; feel free to re-insert them on
aesthetic grounds if you like):

C = 1.0 - (double)R / (double)255;
C = 1.0 - (double)R / 255;
C = 1.0 - (double)R / 255.0;
C = 1.0 - R / 255.0;
 
S

Stef

I want to thank yoo all for the great and complete answers. It really
makes a difference. C is a powerfull language, so powerfull that I
will shoot myself in the foot many more times... But it's worth the
effort..

THnkx.. !!
 
D

Dave Thompson

Shouldn't you have 'C' instead of 'R' and 'M' instead of 'G' in the
second and third argument to printf()?
Probably not. He probably wants C for cyan as the _complement_
computed as 1-x of R=red, M=magenta as the complement of G=green, and
Y=yellow should be the complement of B=blue.

- David.Thompson1 at worldnet.att.net
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top