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

Mixing floats and integers

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



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

Mixing floats and integers
PostPosted: Mon Oct 10, 2022 2:09 am     Reply with quote

I am using the PIC18LF46K22, CCS C compiler v5.110, and MPLAB IDE v8.92.

Recently I ran the following program:
Code:
#include "18LF46K22.h"
#include "math.h"

#use delay(clock=1600000)
#use rs232(UART, baud=9600, errors)

void main()
{
   unsigned int16 x, y, z1, z2, z3, z4, z5, z6;
   
   x = 1000;
   y = 125;

   z1 = floor ( (2.0/3)*x/y + 0.5 );
   z2 = floor ( (2/3.0)*x/y + 0.5 );
   z3 = floor ( (2.0/3.0)*x/y + 0.5 );
   z4 = floor ( (2f/3)*x/y + 0.5 );
   z5 = floor ( (2/3f)*x/y + 0.5 );
   z6 = floor ( (2f/3f)*x/y + 0.5 );

   printf("z1 = %Lu\n", z1);
   printf("z2 = %Lu\n", z2);
   printf("z3 = %Lu\n", z3);
   printf("z4 = %Lu\n", z4);
   printf("z5 = %Lu\n", z5);
   printf("z6 = %Lu\n", z6);
}

Results:
Code:
z1 = 336
z2 = 5
z3 = 5
z4 = 336
z5 = 5
z6 = 5

When converting the ratio 2/3 to a float or double, I thought I would just need to convert either the numerator or the denominator to a float [e.g., 2f/3 or (float) 2/3)] or a double (e.g. 2.0/3); I am assuming that 2.0 is a double. However, the correct results were obtained only when the denominator is converted.

Questions:
1. For those conversions that did not give the correct result (z1 and z4), did I do anything wrong?
2. What is causing z1 and z4 to give 336 instead of 5?
3. Does it matter whether we append an “f” (e.g., 2f) or a decimal point (e.g., 2.0) when converting an integer to a float or double?
Ttelmah



Joined: 11 Mar 2010
Posts: 19548

View user's profile Send private message

PostPosted: Mon Oct 10, 2022 2:45 am     Reply with quote

There is not a double float in CCS (except once you go up to the PIC24/33),
so all the floats are single.

The parser 'knows' it can represent 2.0 exactly as an integer, so does so.
This then means the maths doesn't get forced to be fp maths.
2f, doesn't result in a cast up, it is just that same as 2.0.

However an explicit cast will work.

So:

z1 = floor ( (float)2/3)*x/y + 0.5 );

Will merrily work.

Or

z1 = floor ( (2.1/3)*x/y + 0.5 );
z1 = floor ( (1.99999/3)*x/y + 0.5 );

Because the number is explicitly switched to being a 'float'. Because it
can't be represented as an integer.

With the denominator made into a float the compiler 'knows' FP maths
is required.

It is an oddity in the parsing, that has been reported before. Basically
if the compiler sees a number that can be an integer, it will assume it is
as it parses along the line, until something forces it to not be treated as
an integer.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Tue Oct 11, 2022 10:09 pm     Reply with quote

Thank you, Ttelmah, for your explanation.

I find it really odd that the compiler behaves this way, so I wrote to CCS and asked them whether this behavior was intended or due to a bug.

CCS replied: "It is a compiler bug and will be fixed in the next release."
Ttelmah



Joined: 11 Mar 2010
Posts: 19548

View user's profile Send private message

PostPosted: Wed Oct 12, 2022 1:01 am     Reply with quote

Yes, it is definitely a bug, but so minor as to be not worth worrying about
really. It has been mentioned here before. I think honestly the explicit
cast is clearer, and this has always worked OK.... Very Happy
If they fix it 'great'.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Wed Oct 12, 2022 1:47 am     Reply with quote

This behavior was really unexpected and I think most people would not have suspected the type casting to be the cause of the error. It actually took me quite a while to find out the cause.

Anyway, in line with your suggestion, I have modified all my code to use only the explicit method for type casting, so that the code will work correctly with both earlier and later versions of the compiler.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 5:19 am     Reply with quote

This bug has now been fixed in the new compiler version, v5.111, released today (2022-10-21). See third item below.

From CCS:
Code:
5.111  IDE file history right click now allows you to clear all entries
5.111  A problem with the IDE Wizard starting up on some machines is fixed
5.111  A type problem with a constant float being divided by a constant integer is fixed.
5.111  Duplicate #defines in some devices header files has been fixed.
5.111  Fixed bad SFR names in PIC16F180xx family.
5.111  Fixed an issue where DSM and CRC peripheral functions in the PIC16F180xx family.
5.111  Fixed setup_oscillator() and port_x_pullups() writing to unused registers for PIC16F180xx family.
5.111  Fixed header files for some dsPIC33 devices that caused a compiler error.
5.111  Fixed an issue with missing BROWNOUT_NOSL for some PIC16 devices.
Ttelmah



Joined: 11 Mar 2010
Posts: 19548

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 5:27 am     Reply with quote

Have you tested it?.....

As always, only believe it, when you have tested.
kgng97ccs



Joined: 02 Apr 2022
Posts: 97

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 10:56 am     Reply with quote

Yes, Ttelmah. I have tested the same program (with additional variations), and got the correct results.
Code:
#include "18LF46K22.h"
#include "math.h"

#use delay(clock=1600000)
#use rs232(UART, baud=9600, errors)

void main()
{
   unsigned int16 x, y, z1, z2, z3, z4, z5, z6, z7, z8;
   
   x = 1000;
   y = 125;
   
   z1 = floor ( (2.0/3)*x/y + 0.5 );
   z2 = floor ( (2/3.0)*x/y + 0.5 );
   z3 = floor ( (2.0/3.0)*x/y + 0.5 );
   z4 = floor ( ((float) 2/3)*x/y + 0.5 );
   z5 = floor ( (2f/3)*x/y + 0.5 );
   z6 = floor ( (2/3f)*x/y + 0.5 );
   z7 = floor ( (2f/3f)*x/y + 0.5 );
   z8 = floor ( (2/3)*x/y + 0.5 );
   
   printf("z1 = %Lu\n", z1);
   printf("z2 = %Lu\n", z2);
   printf("z3 = %Lu\n", z3);
   printf("z4 = %Lu\n", z4);
   printf("z5 = %Lu\n", z5);
   printf("z6 = %Lu\n", z6);
   printf("z7 = %Lu\n", z7);
   printf("z8 = %Lu\n", z8);
}

Results:
Code:
z1 = 5
z2 = 5
z3 = 5
z4 = 5
z5 = 5
z6 = 5
z7 = 5
z8 = 0
Ttelmah



Joined: 11 Mar 2010
Posts: 19548

View user's profile Send private message

PostPosted: Fri Oct 21, 2022 10:04 pm     Reply with quote

Good.

Historically, some years ago, CCS was rather poor at launching changes
without much testing. They improved a while ago, but then seemed to
go downhill again, so I treat all new versions as 'beta' till I have done
significant testing.
Caveat.

Nice to have a problem fixed. Very Happy
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