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 support@ccsinfo.com

float printing BUG workaround
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 2:58 pm     Reply with quote

"No cop out " ???

Oh OK? Their are a lot of people here that can come up with a solution (hack) and even give a pretty good explaination of what went wrong (without the source code I might add) before a fix is given. You wouldn't believe how many companys will put things off because they are investing to much of their time on profit rather than fixing their broken problems.


"Maybe someone will organize an effort to make a free, open source PIC environment that's superior to CCS, Microchip, Hi-Tech et. al. For starters, it better handle 256 bit floats perfectly and better darn well have pointers to constants that use NO extra code space to implement . And it better work equally well on a 12C508 as an 18F8720! And don't forget - FREE!!!!!"

Now your saying you are expecting more from FREE then PAY?

I am sure many companys could have gotten together to form community groups by now. Why havn't they? I don't know. There are many success stories out there to prove the point. I'm sure it will happen sooner or later. The sooner the better.

Also, I am not sayin everything needs to be free. Open-source does not always mean FREE.
_________________
-Matt
bluetooth



Joined: 08 Jan 2005
Posts: 74

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 3:13 pm     Reply with quote

Matt:

So sorry - I forgot to put the [HUMOR] .... [/HUMOR] around my "dream compiler"....

Enough of this!

Back to the original topic, it seems as though PCM has found the root of the problem.... maybe CCS will fix it sometime!

Rolling Eyes
Darren Rook



Joined: 06 Sep 2003
Posts: 287
Location: Milwaukee, WI

View user's profile Send private message Send e-mail

PostPosted: Wed Mar 16, 2005 3:15 pm     Reply with quote

kda406 wrote:
but geez, it really shouldn't be that hard.


If floating point math is really that easy to you then why not write your own routines. Rolling Eyes
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 3:20 pm     Reply with quote

take a search on the web. There are open-source projects out there. The more support they get, the sooner you can stop waiting.
_________________
-Matt
PCM programmer



Joined: 06 Sep 2003
Posts: 21420

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 3:22 pm     Reply with quote

To continue working on the problem, I looked at Microchip's AN670,
which tells how to convert floating point to ASCII decimal format.
I modified the AN670 source code as follows:

In floasc.inc, I added 3 more digits (digit_10, digit_1000, digit_1000)
so I could get more significant digits in the result. (The example only
has 4 and I increased it to 7).
Code:
cblock 
        digit_1000           ;Added this
        digit_100            ;Added this
        digit_10             ;Added this
        ones                           
        tenths       
        hundredths       
        thousandths             
      endc

last_digit set thousandths

      cblock
        digit_count 
      endc

SIG_FIG equ 7        ;Changed this to 7.  It was = 4   


Then in main.asm I changed the input value to be 3600.000
Code:
start
                                               ;Load input value of 3600.000
        movlw   0x8A                           
        movwf   AEXP         
        movlw   0x61
        movwf   AARGB0
        movlw   0x00
        movwf   AARGB1
        movlw   0x00
        movwf   AARGB2 
       
        call    float_ascii     


I also changed the processor to a 16F877 and changed the cblock address
in main.c to 0x40, where there is lots of RAM. Then I setup a Watch
window to see the output, and I assembled and ran the program.

The results were:
Code:

digit_1000     0x33       3
digit_100      0x36       6
digit_10       0x30       0
ones           0x30       0
(decimal point here)
tenths         0x30       0
hundreths      0x30       0
thousandths    0x30       0

This shows the correct result of 3600.000, so this means the CCS
runtime code which does the same conversion in printf either has
a bug or maybe it has limited precision. The next step would be to
look closely at the CCS code and find out what's happening.
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 3:29 pm     Reply with quote

bluetooth wrote:
Matt:

So sorry - I forgot to put the [HUMOR] .... [/HUMOR] around my "dream compiler"....

Enough of this!

Back to the original topic, it seems as though PCM has found the root of the problem.... maybe CCS will fix it sometime!

Rolling Eyes


I know where your coming from blue. It's humorous no matter what way you look at it. This all started from my humor. (the open source issue not the bug)
_________________
-Matt
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Wed Mar 16, 2005 5:26 pm     Reply with quote

Point of information all whole numbers can be expressed as a power series
of 2 so it is no surprise that 3600 does also.
CCS floating point
8 bit exponent sign 23 bit mantissa

Now in theory since there are only 23 bits available numbers larger than 2^24-1 will only be approximated in practice due to hot dogging 24 bits are available by taking advantage of the fact that all binary floats will begin with a 1 in the mantissa.
Example
3600 is 111000010000.0 binary but in binary floating point it is normalized as 0.11100001 with an unbiased exponent of 11.
I know some will note there are twelve shifts but convention has the number one normalized as 0.1 with a biased exponent of 127.
Now for the naughty bit since all binary floats it will be 0.1 something we can hot dog and get the sign in there for free by replacing the first 1 with the sign and keeping in mind there is an implied 1.
Keen observers will see that we actually picked up a bit of precision by this hot dog process. That means we have 24 bits in a 23 bit space.
So we have 0110 0001 0000 0000 0000 0000 for storage or hex 61 0 0
now for the exponent we will be 11 shifts higher than the 127 bias which represents (2 power zero or one)

So the exponent is now 138 or hex 8A
the 4 bytes are hex 8A 61 00 00

So much for 3600 but its easier to understand if you look at the number one in float
it is hex 7F 0 0 0
the normalized mantissa is 0.1 binary but its hot dogged to 0.0 since all normalization starts with .1 and the sign is zero
so we have 0000 0000 0000 0000 0000 0000 for the mantissa. Since 127 represents two to the power zero the exponent is 127 hex 7f.
Are you ready for -1?
it is 7F 80 0 0 mantissa is 1000 0000 0000 0000 0000 0000

As I said in my earlier post the CCS error occurs in teasing out the ascii digits with divide by tens during printf
My math says any whole number between -16777215 and 16777215
can be represented by a float without imprecision . Printf should not be getting the trailing .999999 on these numbers this is not an imprecision issue its a bug in its float to ascii code. This is true for any number that can be expressed as a power series of 2 including negative powers. Ex 0.5 should print as 0.5 and 0.125 as 0.125 since they are negative powers of two.
All other numbers ie those bigger than 16777215 irrational numbers ( eg sqrt ) and rational numbers that aren't a power series of two eg 0.1) will be subject to issues many choose to describe as rounding. Its not the rounding your mother knows for that involves taking something to the nearest approximaion at a different level. Its really a fundamental issue with the expression of values in different number base notations. 0.1 in decimal cannot be expressed in binary with the precision it has in the decimal system. Its just how the universe works... 1/3 can't be expressed in decimal notation with precision either.
You should expect 10.0*0.5 to give you 5.0 but
10.0*0.1 to give you 0.999999x the later isn't strictly a rounding error its just the way floating point binary works. Its only accurate to 6 significant digits unless its a power series of two.
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

PostPosted: Thu Mar 17, 2005 12:28 pm     Reply with quote

If you don't mind wasting the code space, I guess this would be an ok work around:

int i;
int digit;
float div;
int32 w = 3600;

float f;
f = w;
div = 1000;
for(i = 0;i<5;i++)
{
digit = f/div;
f-=(digt*div); //or f %= div; don't know if this would work with a float
if(i == 3)
printf(".");
printf("%u",digit);
digit/10;
}

You could also put a flag in there to get rid of leading 0's.

if (digit > 0)
set_flag = 1;


I have used this with other chips that did not offer a printf() with their compiler.

This code was from realled memory and has not been tested.
_________________
-Matt
kda406



Joined: 17 Sep 2003
Posts: 82
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Fri Mar 18, 2005 1:56 pm     Reply with quote

First I just have to reply to this:
Quote:
Quote:
but geez, it really shouldn't be that hard.

If floating point math is really that easy to you then why not write your own routines. Rolling Eyes


Darrin, sure it could be done, but then what am I paying CCS for? Like most, I have a reasonable expectation that software will work as advertised. If it does not, I have another reasonable expectation that it will be corrected, especially if I am paying for maintenance.

Next, I would like to give many thanks to the guys who looked so deeply into this issue, proving that it is indeed a bug. Also, I greatly appreciate the work around code suggestions. Although they may have compiled smaller than my code solution, I have to worry about the next programmer who comes along behind me understanding what appears to be insane antics in my code. Here is what I ended up doing:

Code:
   int32 i32,w;
   w = 3600;
   // The below is a work around for yet another
   // CCS bug, this time to do the equivalent of:
   // printf(TERM,"%5.2f",(float)w/100);
   i32 = w / 100;         // Whole number
   w = w - i32 * 100;      // Remainder
   fprintf(TERM,"Temperature in F: %lu.%02lu\n\r",i32,w);


At least it works dependably and the next guy will understand what I did and why. Thanks.

-Kyle
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Sat Mar 19, 2005 4:29 pm     Reply with quote

Its unfair to expect someone to rewrite printf to get floating point printing working corrrectly. Most floating point numbers will have some unavoidable imprecision when expressed in the decimal system using printf....but thats not an excuse for artificially introducing error into numbers that can be expressed accurately since they are expressed as a power series of 2 up to 2^24. If he hasn't already I hope kda406 submits this as a bug to CCS.
kda406



Joined: 17 Sep 2003
Posts: 82
Location: Atlanta, GA, USA

View user's profile Send private message

PostPosted: Thu Mar 24, 2005 1:29 pm     Reply with quote

Quote:
Its unfair to expect someone to rewrite printf to get floating point printing working corrrectly.

Thank you, Douglas!

I just downloaded 3.222 and tried it on that. Same issue. So I made the following bug report program to illustrate the bug. Here is the program in its entirety. It prints 35.99 when run:
Code:
#include "18F8720.h"

#device ADC=10               // Use 10 bits for A/D conversion
#define SYSTEMCLOCK 11059200      //11.0592 MHz Oscillator
#use delay(clock=SYSTEMCLOCK)
#fuses EC_IO,PROTECT,NOOSCSEN,NOBROWNOUT,NOWDT,PUT,CPD,NOSTVREN,NOLVP,NOWRT,NOWRTD,NOWAIT,MCU,NOWRTC,NOWRTB,NOEBTR,NOEBTRB,CPB

///////////// General IO Pin Definitions /////////////
#define PIN_TERMXMIT      PIN_C6   // XMIT pin to terminal
#define PIN_TERMRCV      PIN_C7   // RCV pin from terminal

///////// IO Port Definitions /////////
#use rs232(baud=115200, xmit=PIN_TERMXMIT, rcv=PIN_TERMRCV, stream=TERM, DISABLE_INTS)

void main(void) {
   float f;
   f = 36.00;
   fprintf(TERM,"%5.2f\n\r",f);
   sleep();
}


I get the feeling that they don't monitor their own forum. So I hope maybe the bug report will get their attention. I have probably reported in the neighborhood of 30 real, repeatable bugs to CCS over the years. Not once have they e-mailed me back to say, "thanks, we have fixed it." So I don't know when we users can know that we can print FP numbers without work-arounds.

-Kyle
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 Previous  1, 2
Page 2 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