PDA

View Full Version : Problem w/ expressions in C

 singularity200601-23-2004, 06:48 PM#include int main(void) { /*LOCAL DEFINITIONS*/ int a; int b; int c; float d; /*STATEMENTS: INPUTS*/ printf("please enter an integer value for a: "); scanf("%d", &a); printf("please enter an integer value for b: "); scanf("%d", &b); printf("please enter an integer value for c: "); scanf("%d", &c); printf("\na=%d, b=%d, c=%d\n", a, b, c); /*STATEMENTS: CALCULATIONS*/ d = a * b / c; /*STATEMENTS: OUTPUT*/ printf("\n\na * b / c = d = %.2f\n\n", d); } For some freakish reason, d keeps equalling 0!! What did I do wrong?? =(
sbp
01-23-2004, 08:32 PM
int * int / int = int converted to float
If the result is less than 1, then the result will be zero because the result is not converted to float until after it's calculated and the int type is whole numbers only. Cast either a b or c as a float in your calculation to convert the result in the calculation.

d = (float)a * b / c; // works
d = (float)a * (float)b / (float)c; // proper, but too much typing
d = (float)(a * b / c) // bad because it's the same as the current line

singularity2006
01-23-2004, 10:03 PM
OooOH..... IC! Thanks, I'll give that a go. I figured there was something wrong w/ data types there. Btw, I'm curious about something, how many digits can a float number be as opposed to other data types? I can't seem to find any references for that.

playmesumch00ns
01-23-2004, 11:15 PM
Read somewhere that float has 6 significant figures, while double has 10. They seemed confused about what a significant figure actually was though, so it might actually be 6 and 10 decimal places.

There's an easy way to test this out though:

#include <iostream>
#include <iomanip>

int main()
{

float f = 1.123456789123456789123456789f
double d = 1.123456789123456789123456789

std::cout << precision( 30 ) << f << endl;
std::cout << precision( 30 ) << d << endl;

return 0;

}

... can't remember if it's precision() or setprecision() or something else like that, but you get the idea.

singularity2006
01-24-2004, 04:45 AM
actually, are u familiar with scientific computations and how to find the correct number of significant figures? I've always wanted to figure out a way to produce a calculator that followed the correct logic. But it got really messy when I tried it in VB. What options do I have in C for that kind of dealy? This is only my third week in C so I don't know much... just printf and scanf.

playmesumch00ns
01-24-2004, 09:04 AM
double post. sorry.

playmesumch00ns
01-24-2004, 09:05 AM
Oops yeah the code I posted was C++. Sorry!

A C translation would be

main()
{
float f = 1.123456789123456789123456789f;
double d = 1.123456789123456789123456789;

printf( "Float: %.30f\nDouble: %.30f\n, f, d );
}

I think....

Anyways, the maths fo significant figures... can't quite remember... GCSE was a while ago...

0.136 has 3 significant figures.

0.106 has 3 sf

0.016 has 2 sf. (or is it 3? this is where it gets tricky)

Basically any number that's not a zero is a significant figure, unless the zero comes between two non-zero digits, in which case it is significant... but there's an exception... anyone care to help me out? I'm struggling...

But anyway, floating point takes care of this all for you, since it's represented as a mantissa and an exponent, kinda like standard notation.

markyjerky
01-26-2004, 02:00 PM
write 0.016 as

1.6 x 10^(-2)

Then you know that you are indicating 2 sig digits, if you are worried about that sort of thing.

singularity2006
01-26-2004, 07:17 PM
That is well and good, however, the rules for calculating significant figures are somewhat cumbersome to write in code through logic. Here's the idea:

123.456 + 12.23 + 12.1

For addition and subtraction, the signficant digits are determined by the decimalThe 12.1 has only 1 decimal, which is considered the maximum number of decimals the answer may have. So the answer is 12.8. The idea is that you cannot have an answer more accurate than your least accurate measurement.

Multiplication and division:
12.2 x 12.02 x 2.0 x 2

For multiplication and division, the significant digits are determined by the number with the fewest digits including decimals. 2.0 has 2 significant digits, but 2 only has one (no decimals). Therefore, the final answer cannot have more than 1 significant digit. The answer would thus be 600

How would you get that kind of logic into C? I was trying to get it in VB too but it was rather confusing. Anyone have any idea of how to program such a logic block?

markyjerky
01-26-2004, 09:54 PM
I don't understand the "issue".

Singularity ... you seem to have stated the domain logic quite well ... now seem like you just need a data structure. How exotic that would be depends on how much speed you need with these calculations ... you have not said much about that yet.

Anyway ...

if you just keep three parts intact after every operation ...

1) The characteristic
2) The exponent
3) The count of sig digits.

Then the programming should be straight forward. You should be able to first lay out the problem in pseudo code ... as the real problem is not how to do this in "C". There would be zillions of approaches in C since it's quite up to the task.

typedef struct temp_SIGDIG
{
short exponent;
long long theCharacter;
unsigned char nSigDig;

} SigDigNumber;

Float2Sig(float x, SigDigNumber* newNum);
Double2Sig(float x, SigDigNumber* newNum);

MultiplySigDigs(SigDigNumber* n1, SigDigNumber* n2);
DivideSigDigs(SigDigNumber* n1, SigDigNumber* n2);

Don't need Subtract I don't think as that's just a case of Add.

I can't envision any of the above being tricky to write.

markyjerky
01-26-2004, 09:58 PM
If the Structure get's you down ...

Just start learning the bit operators in "C" and use various parts of a long long (8 bytes) to contain your

characteristic, exponent, and sigs

bit operators of & ~ | >> << to get at the goods you need. Then you can get rid of the pointers in the declarations !

singularity2006
01-27-2004, 04:59 AM
I haven't learned enough C to program logic statements yet. I'm actually more interested in it for use in VB though. I can program that well enough to write ... sort of. Anyhow, this is more of a pet project at the moment than anything else. Thanks for the info. I'll give it a go again.

For VB, my bog down point was when working with calculations with more than one variable. A lot of times there's a lot of user input for values a, b, c, and d (and more variables if the problem gets long), each with their own number of significant digits. So the way I looked @ it was that I would have to write up a case select or something of that sort to check the number of sig figs per variable and then have the program round off at the very end accordingly. It got weird because I'm not quite comfortable enough with recursion in this manner to check multiple variables over and over like that.

schmu_20mol
01-27-2004, 06:46 AM
while (numbertocheck / a ) <= 1 do
a := a * 10;
INC (numberofdigits);
END;

this should work for you to check the number of digits for your variables - 'simply' make that a procedure you call with each variable.
that's just pseudo-code so you'll have to get it into C yourself if you need it.

actually i'm a bit confused about what you need so it may not fit you at all

gga
01-27-2004, 07:24 AM
Originally posted by singularity2006
actually, are u familiar with scientific computations and how to find the correct number of significant figures? I've always wanted to figure out a way to produce a calculator that followed the correct logic. But it got really messy when I tried it in VB. What options do I have in C for that kind of dealy? This is only my third week in C so I don't know much... just printf and scanf.

And that's more or less all you'll need.
Read ALL the options of printf and sprintf:

printf("%2.e", 0.0004);

Will already deal with printing in scientific notation.

One of the interesting things is that floating point numbers are stored in a form of scientific notation inside the computer (which also does tend to create other precision headaches, too).

The float type contains 32 bits: 1 for the sign, 8 for the exponent, and 23 for the mantissa. Its range is +/– 3.4E38 with at least 7 digits of precision.

The double type contains 64 bits: 1 for the sign, 11 for the exponent, and 52 for the mantissa. Its range is +/– 1.7E308 with at least 15 digits of precision.

The long double type contains 80 bits: 1 for the sign, 15 for the exponent, and 64 for the mantissa. Its range is +/– 1.2E4932 with at least 19 digits of precision. With the Microsoft C compiler, the representation of type long double is identical to type double.
Long double is also hardly ever used in any code, particularly these days.

ANSI C afaik does not have a built-in standard function to count decimal digits of floating point numbers. But one could be implemented by turning the value into a string (see sprintf or _gcvt, _fcvt if non-standard ansi) and then counting the number of characters past the '.', disregarding trailing 0's (if a period is available, that is). If you look around the web, I'm sure you will find some code to do this somewhere.

Note that current Intel processors many times do floating point operations in up to 80 bits and the result is later truncated. This is another headache to deal (in addition to the IEEE fp standard) with when you actually want lack of precision. But these problems are not inherent to C but to modern computers in general.
If you want better control of floating point, there are free libraries available that offer more precision and their own floating point types by trading some speed. But you likely don't want to go there.

CGTalk Moderation
01-17-2006, 06:00 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.