View previous topic :: View next topic |
Author |
Message |
Nick Alexeev Guest
|
Integer division |
Posted: Wed Dec 11, 2002 6:44 pm |
|
|
Colleagues,
Here is the problem.
g_sLoad.iSkip = g_sLoad.iPeriod * 15 / 255;
If g_sLoad.iPeriod is greater then 17, g_sLoad.iSkip gets the value of 0 (zero), though it shoult be 1. What is the most conventional workaround for this problem?
Thank you!
Sincerely,
Nick
___________________________
This message was ported from CCS's old forum
Original Post ID: 9987 |
|
|
Nick Alexeev Guest
|
Re: Integer division |
Posted: Wed Dec 11, 2002 7:32 pm |
|
|
Also could anyone point me to the list of data conversion bugs/features.
Nick
___________________________
This message was ported from CCS's old forum
Original Post ID: 9989 |
|
|
kolio Guest
|
Re: Integer division |
Posted: Thu Dec 12, 2002 2:15 am |
|
|
:=Colleagues,
:=
:=Here is the problem.
:=
:=g_sLoad.iSkip = g_sLoad.iPeriod * 15 / 255;
:=
:=If g_sLoad.iPeriod is greater then 17, g_sLoad.iSkip gets the value of 0 (zero), though it shoult be 1. What is the most conventional workaround for this problem?
:=
:=Thank you!
:=
:=Sincerely,
:=Nick
My suggestion is just a guess as far as I don't know the type of the variable - byte or word, but you know 15*17 =255 and any greater value will overflow the registers if the aritmetics are 8-bit. You know int is 8-bit wide in CCSC My assumption is that first the multiplication is performed and then the division. Why don't you just
g_sLoad.iSkip = g_sLoad.iPeriod / 17;
or declare the members iPeriod and iSkip as long:
struct {
...
long lSkip;
long lPeriod;
...
} g_sLoad;
Then I guarantee that
g_sLoad.lSkip = g_sLoad.lPeriod * 15 / 255;
will work correct for lPeriod <= 4369
Wish you luck!
___________________________
This message was ported from CCS's old forum
Original Post ID: 9991 |
|
|
kolio Guest
|
Re: Integer division |
Posted: Thu Dec 12, 2002 2:35 am |
|
|
He-he,
I expected that such a famous compiler as CCS C is well optimized, but in this case:
Var1 = Var2 * Const 1 / Const 2 ,
where Const2 \% Const 1 = 0 and Const3 = Const2 / Const1, instead of optimizing to:
Var1 = Var2 / Const3 ,
the compiler performs two secuential multiplications. Well, my version is pretty old and I hope they already impoved it ;-)
___________________________
This message was ported from CCS's old forum
Original Post ID: 9993 |
|
|
Jon Fick Guest
|
Re: Integer division |
Posted: Thu Dec 12, 2002 1:09 pm |
|
|
If you are unsure of the order of operation and want to force the order to be sure, just implement the equation in separate instructions.
g_sLoad.iSkip = g_sLoad.iPeriod * 15 / 255;
would become
g_sLoad.iSkip = g_sLoad.iPeriod * 15;
g_sLoad.iSkip /= 255;
That's an easy way around what might be a bug in operator order, but allows me to continue to use what I think is the best compiler for the money.
Or course, you would need to deal with the fact that anything over 17 will wrap in an 8-bit variable.
Jon
___________________________
This message was ported from CCS's old forum
Original Post ID: 10006 |
|
|
Sherpa Doug Guest
|
Re: Integer division |
Posted: Thu Dec 12, 2002 1:36 pm |
|
|
:=He-he,
:=I expected that such a famous compiler as CCS C is well optimized, but in this case:
:= Var1 = Var2 * Const 1 / Const 2 ,
:=where Const2 \% Const 1 = 0 and Const3 = Const2 / Const1, instead of optimizing to:
:= Var1 = Var2 / Const3 ,
:=the compiler performs two secuential multiplications. Well, my version is pretty old and I hope they already impoved it ;-)
Since
Skip = Period * (15 / 255)
produces a different answer under some conditions of 8 bit truncation than
Skip = (Period * 15) / 255
I would consider the compiler precalculating 15/255 to be a dangerous optimization. If I wanted the compiler to do the optimization I would add my own parens. Without the parens I would expect the compiler to do what it is told: Multiply, Truncate, then Divide.
If you want to avoid the truncation you should use casting.
___________________________
This message was ported from CCS's old forum
Original Post ID: 10008 |
|
|
kolio Guest
|
Re: Integer division |
Posted: Fri Dec 13, 2002 2:10 am |
|
|
The point in the post was not the truncation and some possible calculation error, but the optimization. It should be heuristic rather than formal. I was talking about one certain case when the reminder is 0, as you might notice. Let's agree that the purpose of the optimization is not to introduce confusions, but to reduce the run-time operations. And actually I won't stop using PSW in the future ;-)
___________________________
This message was ported from CCS's old forum
Original Post ID: 10017 |
|
|
sachin_plr Guest
|
Re: Integer division |
Posted: Fri Dec 13, 2002 3:57 am |
|
|
Hi,
If iPeriod is char then by type casting as folows
will get correct result.
g_sLoad.iSkip = ((long)g_sLoad.iPeriod * 15) / 255;
Regards
sac
___________________________
This message was ported from CCS's old forum
Original Post ID: 10022 |
|
|
Nick Alexeev Guest
|
Thank you, now it works! |
Posted: Mon Dec 16, 2002 12:18 am |
|
|
g_sLoad.iSkip = ((long)g_sLoad.iPeriod * 15) / 255;
did the trick. Thanks for the optimization hints also.
Nick
___________________________
This message was ported from CCS's old forum
Original Post ID: 10061 |
|
|
Kurt Franke Guest
|
Re: Integer division |
Posted: Mon Dec 16, 2002 9:37 pm |
|
|
Even when the remainder is zero the optimization is not "safe".
int8 a;
int8 i = 34;
1> a = i * 255 / 15; // is an overflow
2> a = i * (255 / 15); // == 2
3> a = i / 17; // also 2
The compiler can simplify 2 to 3 b/c it cannot change
the result. But it cannot change 1 to 3 because it could
(and in this case does) change the result.
-Kurt
:=The point in the post was not the truncation and some possible calculation error, but the optimization. It should be heuristic rather than formal. I was talking about one certain case when the reminder is 0, as you might notice. Let's agree that the purpose of the optimization is not to introduce confusions, but to reduce the run-time operations. And actually I won't stop using PSW in the future ;-)
___________________________
This message was ported from CCS's old forum
Original Post ID: 10082 |
|
|
|