View previous topic :: View next topic |
Author |
Message |
Chicky
Joined: 04 Aug 2005 Posts: 21
|
Problem with calculation results |
Posted: Wed Apr 02, 2008 9:31 pm |
|
|
Why is this happening?
Code: |
#include <math.h>
int16 Red, Green, Blue;
double FRed, FGreen, FBlue, Net1;
FRed=Red/16*0.088;
FGreen=Green/16*0.88;
FBlue=Blue/16*8.157;
Net1=0-FRed+FGreen-Fblue+99.348; |
Results:
For Red=253 Green=255 Blue=252
FRed=1.32 >> correct
FGreen=13.20 >> wrong! should be 14.025
FBlue=122.35 >> wrong! should be 128.473
Net1=-11.12 >> correct but only using the prev wrong values (FGreen & FBlue)
Which part did I go wrong? Is it the var types? FYI I've tried wif several other RGB values..
Thanks for ur suggestions! |
|
|
Guest_7068 Guest
|
|
Posted: Wed Apr 02, 2008 10:05 pm |
|
|
What chip are you using?
What is your compiler version?
Try typecasting which works in some cases
Code: |
FGreen= (double) (Green/16.0*0.88); // Notice the 16.0 instead of just 16
|
|
|
|
Chicky
Joined: 04 Aug 2005 Posts: 21
|
|
Posted: Wed Apr 02, 2008 10:12 pm |
|
|
Ok I'll try that.. thanks
I'm using Pic16f877a wif CCS compiler V4.009 |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Thu Apr 03, 2008 1:17 am |
|
|
Yes type casting should work.
your code is doing the following:-
FGreen=Green/16*0.88;
Green (Int16) = 255
Int16 division Green/16 (255/16) = 15
double mult (15 * 0.88) = 13.2 (your answer)
The following should fix it:-
Either
FGreen = Green / 16.0 * 0.88 (Force double division by using .0 e.g 16.0) or
FGreen = (double)Green/16*0.88 (Use Green as a double for calculation)
Personally I would use the second option (double) to show type casting, makes it better to read later on when you come back to it and need to change something. Seeing (double) there, you will know it is a floating point calculation! |
|
|
Ttelmah Guest
|
|
Posted: Thu Apr 03, 2008 2:32 am |
|
|
Or. save some time:
Code: |
#include <math.h>
int16 Red, Green, Blue;
double FRed, FGreen, FBlue, Net1;
FRed=Red*0.00521739;
FGreen=Green*.055;
FBlue=Blue*.5098134;
Net1=0-FRed+FGreen-Fblue+99.348;
|
It is well worth remembering for calculations like this, that multiplication, is faster than division. A FP multiply, typically takes only half the time of a division. Hence it is much better, to multiply by the reciprocal of a constant value like this. Also, you can solve the second part of the equations yourself beforehand, to save more time. So multiplying by the factors shown, solves the original problem (forces the maths to only be float), and will take a lot less time as well.
Best Wishes |
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Thu Apr 03, 2008 7:14 am |
|
|
Damn, I should have spotted that one Ttelmah |
|
|
Ken Johnson
Joined: 23 Mar 2006 Posts: 197 Location: Lewisburg, WV
|
|
Posted: Thu Apr 03, 2008 8:24 am |
|
|
FGreen=Green/16*0.88;
or parens:
FGreen=Green/(16*0.88);
Then, multiply vs divide:
FGreen=Green * (0.88/16);
Because they are constants, the compiler does the math in parens (i.e., at compile time, not run time). I like to let the compiler do the work. Also use pre-processor #defines to clarify what these constants mean, and to change a value in only one place if something changes (gear ratios, amplifier gain resistors, etc)
Ken |
|
|
Chicky
Joined: 04 Aug 2005 Posts: 21
|
|
Posted: Sun Apr 06, 2008 8:37 pm |
|
|
OMG this program keep messing wif my head.. lol..
where did i go wrong here?
Code: | //Net1
Net1=(-Red*(0.0881/16.0)-Green*(2.272/16.0)+Blue*(0.2682/16.0)+99.348)*(-1.0);
delay_ms(200);
printf("\r\n%f",Net1);
delay_ms(200);
Net1=(double)(pow(10.0,Net1));
printf("\r\n%f",Net1);
delay_ms(200);
Net1=(double) (1.0/(Net1+1));
delay_ms(200);
printf("\r\n%01.9f",Net1);
delay_ms(200); |
results
for R=255 G=255 B=255
-426.86
0.00
0.000000000
how come Net1 = 0?? it should be 1.00 |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Apr 06, 2008 11:36 pm |
|
|
Chicky wrote: | how come Net1 = 0?? it should be 1.00 | pow(10, -426.86) = 0.000000000..................00001 (425 zeroes after the dot).
So small the result is rounded down to zero. |
|
|
ChickyMeal Guest
|
|
Posted: Sun Apr 06, 2008 11:44 pm |
|
|
Hi Chielkra..
If u notice after the 10th power operation, i added 1 to the results followed by 1/Net1.. so the final result should be 1 instead of 0 rite? |
|
|
Ken Johnson
Joined: 23 Mar 2006 Posts: 197 Location: Lewisburg, WV
|
|
Posted: Mon Apr 07, 2008 6:04 am |
|
|
printf("\r\n%01.9f",Net1);
Maybe has something to do with the format spec %01.9f ? ? ? Is that supposed to be %10.9f?
Try just %f
Ken |
|
|
|