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

CCS math operation problems
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Oct 13, 2012 2:05 pm     Reply with quote

Quote:

Problem is when code tries to divide a number like res1=99999999/1000
the answer res is something like 127 !?

I don't have the PCD compiler so I can't offer help on bugs, but my
advice is, if you want help from people who do have the compiler,
then post a short test program that shows your problem.

For example, I made this program for the 18F4520 and ran it in MPLAB
simulator and it works OK. Here's the output:
Quote:

res1 = 99999

Test program:
Code:

#include <18F4520.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

//======================================
void main(void)
{
int32 res1;

res1 = 99999999;

res1 /= 1000;

printf("res1 = %lu \r", res1);

while(1);
}

Make a complete, testable program very similar to that one.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Oct 14, 2012 2:18 am     Reply with quote

I didn't notice that the original post was referring to PCD. Two additional comments:

float is working correctly both with PCH and PCD. I can't reproduce your results in this regard.

I still don't understand the idea behind the CCS _fixed operations. With PCD, it's clearer what the compiler
does, but I don't see why.

As mentioned, there's an 16-Bit overflow problem involved with the original multiply example.
Thus I changed the b value.

a=4.12; // stores 411 (!!!)
b=1.13; // stores 113
c=a*b; // result 464.00
d=a/b; // result 0.03

Interestingly, 46400 is not the product of 411 and 113.
It's 411*113*100/100

If you are interested in the details, here's the assembly listing.
Code:
..............................    a=4.12;
00E28:  MOV     #19B,W4        : W4 = 19B
00E2A:  MOV     W4,92A         : [92A] = W4
..............................    b=1.13;
00E2C:  MOV     #71,W4         : W4 = 71
00E2E:  MOV     W4,92C         : [92C] = W4
..............................    c=a*b;
00E30:  MOV     92A,W4         : W4 = [92A]
00E32:  MOV     92C,W3         : W3 = [92C]
00E34:  MUL.UU  W4,W3,W0       : W1:W0 = W4 * W3
00E36:  MOV     W0,W5          : W5 = W0
00E38:  MOV     W5,W4          : W4 = W5
00E3A:  MOV     #64,W3         : W3 = 64
00E3C:  REPEAT  #11            : Repeat next instruction (11 + 1) times
00E3E:  DIV.U   W4,W3          : W0 = W4/W3  ::  W1 = W4 % W3
00E40:  MOV     #64,W4         : W4 = 64
00E42:  MUL.UU  W4,W0,W0       : W1:W0 = W4 * W0
00E44:  MOV     W0,92E         : [92E] = W0
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Sun Oct 14, 2012 1:30 pm     Reply with quote

As an 'interesting', 4.137, refuses to compile if you try to use the _fixed() syntax.

It is worth perhaps noting that CCS has an 'example' of doing fixed arithmetic, and avoids this ability entirely, doing it themselves.

On castek's attempt at DIY, this seems fundamentally flawed. Of course it'll go wrong with 99999999/1000, the values are only int16 for the incoming numbers.

Best Wishes
castek



Joined: 12 Jul 2012
Posts: 14

View user's profile Send private message

PostPosted: Mon Oct 15, 2012 5:43 am     Reply with quote

ok..


I just want to multiply unsigned int16 5000 * unsigned int16 5000 = unsigned int32 25000000, and then divide it per 1000 so I get unsigned int32 25000 so I can store in a unsigned int16 without overflows..

seams easy:

unsigned int16 ind1=5000;
unsigned int16 ind1=5000;
unsigned int32 res32;
unsigned int16 res16;

res32=_mul(ind1,ind2);
res32=res32/1000;
res16=res32;

What´s wrong? How can I do it?

¿¿How can I do it??
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Mon Oct 15, 2012 8:32 am     Reply with quote

First, you don't need the 32bit value anywhere.
Code:

unsigned int16 ind1=5000;
unsigned int16 ind2=5000;
unsigned int16 res16;

res16 = (_mul(ind1,ind2)/1000);

The '_mul' function, called with two int16 values, generates an int32 result. This then merrily divides by 1000 using int32 maths, and the result is directly converted to int16.

The traditional way to do this which involved slightly more time, is to use a cast:
Code:

unsigned int16 ind1=5000;
unsigned int16 ind2=5000;
unsigned int16 res16;

res16 = ((int32)ind1*ind2)/1000;


Which then uses int32 maths (the cast forces this), and produces a 16bit result.
Both correctly give a 25000 result for me, with the former saving 56 instructions.

Best Wishes
castek



Joined: 12 Jul 2012
Posts: 14

View user's profile Send private message

PostPosted: Mon Oct 15, 2012 9:07 am     Reply with quote

I´ve executed your code and res16=511
When I use ind1=500 and ind2=500, and divide per 1000 result is 3, if I divide per 100 result is 2500 and if I divide per 10 result is 25000.

Something does not work on PCD... Do you use PCD compiler ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Mon Oct 15, 2012 9:21 am     Reply with quote

Yes, I compiled that for your chip with PCD, and for both calculations the result was correct.
Only difference, I haven't got version 4.130, had to use 4.134, and 4.137. Both gave correct results.
Now, I do remember a thread here about maths problems with PCD a little while ago, which would have been about when 4.130 was launched....

Best Wishes
castek



Joined: 12 Jul 2012
Posts: 14

View user's profile Send private message

PostPosted: Mon Oct 15, 2012 2:16 pm     Reply with quote

I compiled the same code with PCD 4.134 but got same wrong result... this is quite weird !! (I have updated to 4.134)
Code:

unsigned int16 ind1=5000;
unsigned int16 ind2=5000;

unsigned int16 res16;
unsigned int16 div=1000;

res16 = _mul(ind1,ind2)/div;

printf(LCD_PUTC, "\fA %u B %u \n res= %u", ind1,  ind2,res16);

maybe problem is in printf !?

Result for res16 is 511...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Oct 15, 2012 4:49 pm     Reply with quote

I don't have PCD, but this thread says that vs. 4.134 did have printf problems:
http://www.ccsinfo.com/forum/viewtopic.php?t=48569
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Mon Oct 15, 2012 4:51 pm     Reply with quote

just for giggles, try %lu instead of %u and see if anything changes.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Oct 16, 2012 1:02 am     Reply with quote

Could easily be a printf bug, I was watching the variable in a debugger.
Have just tried using sprintf, with 4.137, and %u, %lu (shouldn't be needed PCD treats an int as int16), and %d, all gave the same output of 25000.

Best Wishes
castek



Joined: 12 Jul 2012
Posts: 14

View user's profile Send private message

PostPosted: Tue Oct 16, 2012 3:24 am     Reply with quote

I have changed but got same problem, result is still 511. How can I see the true value for res16?? I dont know if its a printf problem or a PCD math problem.

However I found a bad solution.

PCD gives a good result that way:

unsigned int16 ind1=5000;
unsigned int16 ind2=5000;

unsigned int16 res16;
unsigned int32 res32;

res32 = _mul(ind1,ind2)/100;
res32=res32/10;
res16=res32;


printf(LCD_PUTC, "\fA %Lu B %Lu \n res= %Lu", ind1, ind2, res16);

Dividing per 1000 does not work, but if I divide fist per 100 and then per 10 (which is the same as dividing per 1000), now it works.... Finally I think it´s a PCD problem

¿¿Did you tried it in PCD 4.134??


Last edited by castek on Tue Oct 16, 2012 4:29 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Oct 16, 2012 4:27 am     Reply with quote

Depends what debugging tools you have got.

Free one, is MPLAB, and run it in MPSIM.

Is anything else being done, while this code is working?. I find it too 'odd' that it gives perfectly normal results for me. Something overrunning an area of memory, and corrupting a variable, or something happening in an interrupt, are obvious suspicions.

Best Wishes
castek



Joined: 12 Jul 2012
Posts: 14

View user's profile Send private message

PostPosted: Tue Oct 16, 2012 5:14 am     Reply with quote

Well.. I´m printing the result in an LCD in proteus... maybe there´s the problem. I´m using PCD 4.134 same as you. However I´m downloading the demo version of PCD 4.137 to check... I´m getting crazy, dont know why I cant divide a number higher than 1000 without errors. The extrange thing is that I can divide per 100 but not per 1000... !?!
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Oct 16, 2012 5:42 am     Reply with quote

PIC rule #0 : READ PIC101 !!

PIC rule #1 : GET RID OF PROTEUS !!

PIC rule #2 : ALWAYS OBEY rule #1 !!

PIC rule #3 : PROTEUS is full of bugs,errors, faulty DRCs
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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