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

Question on sending a floating point value to Hyperterminal

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Arizona Chris



Joined: 20 Dec 2014
Posts: 69
Location: Arizona

View user's profile Send private message Visit poster's website

Question on sending a floating point value to Hyperterminal
PostPosted: Sun Mar 29, 2015 8:16 pm     Reply with quote

Greetings all,

Having great fun connecting our newly built TTL to 232 converter board between the PC and the 877a processor and sending text to Hyperterminal. With integers 8 and 16, and of course text it works fantastic. But I tried a floating point number and I get nothing close!

I would assume that sending a floating value to an LCD is the same issue. Where have I gone horribly wrong here? An example is when I send a value of say 1.8 I got some huge 10 digit number with one decimal with
%3.1w in the print statement. So I tried just plain number 2. Got 12.8 on the screen. Oh my.

Here is most of the pertinent code, with the silly comments at the top of the program deleted. Help!

Code:
#include <16F877A.h>  //Normally chip, math, etc.  used is here.

//Directives and Defines:
#device ADC=10  //Set ADC when used to 10 bit = 0 - 1023
#fuses NOPROTECT,HS,NOWDT   //xtal is used
#use delay(crystal=10MHz)   //xtal speed
#use fast_io(ALL)          //must define tris below in main when using this

//for LCD:
#use rs232(baud=9600, xmit=Pin_B1, bits=8, parity=N,stream=TERMINAL)



void main(void) {

   // Set TRIS I/O directions, define analog inputs, compartors:
      set_tris_A(0b11111);
      set_tris_B(0b11111000);
      set_tris_C(0b11111111);
      set_tris_D(0b11111111);
      set_tris_E(111);
     
      //(analog inputs digital by default) 

   //Initialize variables and Outputs:  --------------------------------------
   output_low(Pin_B0);  //status off
   delay_ms(1000);  //LCD warmup time
   int8 n = 255;
   int16 x = 50000;
   float y = 2;
   //----------------------------------------------------------------

//MAIN PROGRAM:

while (true)   {

   output_high(Pin_B0);
   delay_ms(250);
   output_low(Pin_B0);
   delay_ms(250);
   
   //send message to Terminal:
   
   delay_ms(1000);
   
   fprintf(TERMINAL,"ROBOT BOARD= %u"n);  //text plus integer
   fprintf(TERMINAL,"\n\r");              //New line, Carrige Return
 
   delay_ms(250);
   
   fprintf(TERMINAL,"Value= %Lu"x);  //text plus Int 16 (word)
   fprintf(TERMINAL,"\n\r");         //New line, Carrige Return
 
   delay_ms(250);
   
   fprintf(TERMINAL,"floating= %3.1w"y);  //text plus floating
   fprintf(TERMINAL,"\n\r");              //New line, Carrige Return
 
   delay_ms(250);
   
   
    }  //elihw
 
}  //niam
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 29, 2015 8:25 pm     Reply with quote

Look in the CCS manual under 'printf'. Look at the format specifiers
for floating point. 'w' is not one of them.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Arizona Chris



Joined: 20 Dec 2014
Posts: 69
Location: Arizona

View user's profile Send private message Visit poster's website

Fprintf
PostPosted: Sun Mar 29, 2015 8:59 pm     Reply with quote

Page 233 at the bottom. That doesn't mean I know how to use it...

What would you use?

Chris
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 29, 2015 9:19 pm     Reply with quote

There's a table of format specifiers:
Code:

f  Float with truncated decimal
g  Float with rounded decimal
e  Float in exponential format
w  Unsigned int with decimal place inserted. Specify two
numbers for n. The first is a total field width. The
second is the desired number of decimal places.


So, use "%7.1f" for starters.
Arizona Chris



Joined: 20 Dec 2014
Posts: 69
Location: Arizona

View user's profile Send private message Visit poster's website

Float
PostPosted: Sun Mar 29, 2015 9:49 pm     Reply with quote

Ok, I figured it all out. The problem seems to have been the example in the manual is for w AND f for format specifiers, and I got them mixed up.

%f. Works great for 2 numbers after the decimal, and %8.3f easily came out correct on the terminal, with three numbers after the decimal. Only one case now was not quite right - when I defined a float like this:

Float x = 65000.123

And it replaces the last "3" with a zero to give on the terminal:

65000.120

I'll be happy with two decimals, that's more than I'll ever need! Just curious why it did this.

Chris
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Mar 29, 2015 11:15 pm     Reply with quote

The floating point format used by CCS only has about 7 digits of precision.
CCS uses the 32-bit Microchip floating point format.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Mar 30, 2015 12:54 am     Reply with quote

You have now met the critical 'problem' of floating point, and why it is not used for things like financial calculations.....

A '32bit float', has 23 bits used for the actual 'number' (it's actually technically a 24bit mantissa, with the top bit always set to '1', with just 23bits stored). So binary numbers from 1000 0000 0000 0000 0000 0000 to 1111 1111 1111 1111 1111 1111 1111. In decimal 8388608 to 16777215. A range of 8388607 possible values. These are then 'scaled' by the exponent, to give the number to be displayed. So just under 7 digits of actual 'accuracy' (6.8 digits), but over an enormous 'range'. It is this large range that can make floats useful, but it comes at a huge cost in accuracy.
Compare (for instance), with a 32bit signed integer value (31 bits for the number). If this is used to store milli-values (so an integer count of 0.001's), it can store a value up to 2147482.646, with _every_ possible value useable. An accuracy of 9.2 digits. So using 'floats' here costs 2.4 digits of numeric accuracy.....
The float is also much harder for the processor to work with. A floating point addition for instance, takes eighty five times longer than the same addition in int32!... The actual code involved is also very much larger (typically at least twice the size for a set of FP maths versus int32).
This is why you will see it often suggested here that it is much better to design your code to use scaled integer maths, rather than floating point.
Now like all things it is not absolute (I use FP, for example on a recent project with a logarithmic scaling on the ADC response, there is no simple substitute), but for 99% of the things seen in this forum, it is safer, simpler, and quicker to design the maths from the start to use integer.

On the 'financial' example, if you are Bill Gates, and happen to want to add up 1000026.66 dollars, with 451021.66 dollars, in int32, using integer 'cents', this will give exactly 1451048.32, while in FP, you will get 1451048.40!. Eight cents too much!....
(Maybe this is how he has made a lot of his money.).

So if you are using fixed point x.xxx values, consider whether you could work in integer 'milli-x' values instead of using float. Financial programs generally do exactly this.

Float's, 'look convenient', but this convenience comes at a cost.....
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

Re: Float
PostPosted: Mon Mar 30, 2015 3:43 am     Reply with quote

Arizona Chris wrote:
%f. Works great for 2 numbers after the decimal, and %8.3f easily came out correct on the terminal, with three numbers after the decimal.

I'll be happy with two decimals, that's more than I'll ever need!


It's not about the number of decimal places, its about significant figures. The number of sig. figs is directly related to the length of the mantissa in the floating point format. Those sig figs. could have the decimal point anywhere, The more bits in the mantissa, the more sig. figs. Where those sig. figs happen to be in real number space is down the the exponent. So the length of the exponent determines the overall range of floating point, the mantissa length determines the precision.

Floating point has some perhaps unexpected oddites. These vary from floating point format to format. For example, in formats with binary exponents, including the very commom 32 bit IEE754 that most people think of as "THE floating point format", integers, 1, 10, 100 etc, can be precisely represented up to that allows by the length on the mantissa, but "simple" decimals can't, such as 0.1 and 0.01- 0.1 would come out as something like 0.0999997. Binary related decimals, however, are precise: 0.5, 0.0625 etc. So in floating point, 1.0/10.0 * 10.0 is NOT equal to 1.0. However, 1.0/16.0 * 16.0 is equal to 1.0. In floating point formats with decimal exponents (rare these days) it would be the other way round.

If the precision of floating point is "good enough", then its good enough. But don't be too certain that all the errors will be in any particular direction or will somehow cancel each other out. They might not, and culmulative errors can be nasty to fix.

Floating point is also very, very slow compared to integers.

All that said, floating point is very useful, and by no means to be avoided at all costs. You just need to be aware of its limitations, and apply it with care.
Arizona Chris



Joined: 20 Dec 2014
Posts: 69
Location: Arizona

View user's profile Send private message Visit poster's website

Floating
PostPosted: Mon Mar 30, 2015 6:24 am     Reply with quote

Thanks for the explanations! You guys are the greatest. 7 figures of precision is awesome as far as I'm concerned. Jay, you are right - for 99 percent of micro apps we need only to use integer math and it does the job admirably. On occasion, for small numbers less than 100, a few decimals can come in handy.

Thanks again for all the very understandable explanations. The past decade I have used only integer math at work, and never needed to do floating. Anyway, PBP won't do it anyway. ;)

Chris
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