CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Re: Integer division

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Nick Alexeev
Guest







Integer division
PostPosted: Wed Dec 11, 2002 6:44 pm     Reply with quote

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
PostPosted: Wed Dec 11, 2002 7:32 pm     Reply with quote

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
PostPosted: Thu Dec 12, 2002 2:15 am     Reply with quote

:=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
PostPosted: Thu Dec 12, 2002 2:35 am     Reply with quote

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
PostPosted: Thu Dec 12, 2002 1:09 pm     Reply with quote

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
PostPosted: Thu Dec 12, 2002 1:36 pm     Reply with quote

:=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
PostPosted: Fri Dec 13, 2002 2:10 am     Reply with quote

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
PostPosted: Fri Dec 13, 2002 3:57 am     Reply with quote

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!
PostPosted: Mon Dec 16, 2002 12:18 am     Reply with quote

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
PostPosted: Mon Dec 16, 2002 9:37 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group