Casting return of float function into long

Is this right way of casting return of float function into long ?

unsigned long calibration=5;
calibration = (unsigned long)tempco(_temperature, calibration_temperature, (float)calibration);

tempco function is returning float.

IDE is not giving any notices that this is wrong but I never met this type of casting before.

surepic:

unsigned long calibration=5;

calibration = (unsigned long)tempco(_temperature, calibration_temperature, (float)calibration);

why pass calibration to the function and then assign the return back to calibration?

you can just pass the variable by reference and alter it.

What does your function look like?

tempco function is getting 3-rd parameter as float Its being used in other functions which variables are floats. only calibration and only in 1 function is unsigned long that's why not to change all functions I want to squeeze it inside tempco.

Delta_G:
If your function wants a float and you have a long you don't need to cast anything. The compiler is smart enough to do that one for you.

I checked both ways and both ways are working I`m getting right values with both ways. I want to know if the way I wrote is considered as right way? There must be kinda recommended and not recommended ways I think :slight_smile:

surepic:
tempco function is getting 3-rd parameter as float Its being used in other functions which variables are floats. only calibration and only in 1 function is unsigned long that's why not to change all functions I want to squeeze it inside tempco.

well, just show the function...

Float tempco(float a,float b, float c){
float d=Sqrt(sq(a*b*c ))*0.034565;
c=d*sq(a/b);

return c;


}

Writing from phone sorry if any syntax errors.

So how pass by reference if float and unsigned int have different byte length? Thats why i am casting unsigned int into float to make tempco() work.

surepic:
So how pass by reference if float and unsigned int have different byte length?

void setup() 
{
  Serial.begin(9600);
  uint16_t value = 4;
  tempco(123.0, 789.0, value);
  Serial.println(value);
}

void loop() 
{
  

}

void tempco(float a,float b, uint16_t& c)
{
  float d = sqrt(sq(a * b * c )) * 0.034565; 
  c = d * sq(a/b);
}

Thats not gonna work in my case. Too many functions are sending floats to tempco and its dealing with them but 1 function is using int instead of float so i am casting int to float. Passing by reference how will work if int has twice smaller byte width than float? In your example tempco is expecting address of uint not float.

Delta_G:
Once again, if the function expects float and you have int then you don't need any cast. The compiler will handle the promotion for you. Just pass the int in there and the cast to float happens automagically.

or just make an overload of the function...

or just make an overload of the function...

That would be useful if the two different functions did different things. If the only reason for the int vs. float variant is to not require an implicit or explicit cast, duplicating code is not the right thing to do.

Do not cast the output to long, use round() or ceil() or floor() and get better defined behavior.

float tempco (float a, float b, float c)
{
  return sqrt(sq(a * b * c )) * 0.034565 * sq(a / b);
}

long x = round(tempco (a, b, c));

I don't think there's any convention on what is correct there.

In many cases, these are the conventions that establish what should be 'correct'; scientific arena is not an exception. For example:

Case:A

float ampT = 100*(1.1/1024)*0xE9;
Serial.println(ampT, 2);                             //prints correct value : 25.03 

float ampT = (float) 100*(1.1/1024)*0xE9;
Serial.println(ampT, 2);                            //prints correct value: 25.03

//--------------------------------------------------------------------------------------
Case: B

float ampT = 10000*100*(1.1/1024)*0xE9;
Serial.println(ampT, 2);                    //prints incorrect value:4244.97 instead of: 250292.97

float ampT = (float) 10000*100*(1.1/1024)*0xE9;
Serial.println(ampT, 2);                    //prints correct value:250292.97

//--------------------------------------------------------------------------------------------
In Case:A whether we cast or not, there are correct results.

In Case:B, we must cast to get the correct result.

So, I follow what my teacher has advised me -- always do the cast (follow the convention), and you are safe! (Casting forces the machine to come out of confusion and to produce the expected data type; declaration of correct data type for the holding variable is not enough.)

Delta_G:
No cast needed. Just need to make sure your first constant is a float.

Only true if the expression evaluation order does not screw up things

float ampT = (float) (10000100)(1.1/1024)*0xE9;

Delta_G:
No reason to start with it as an int and cast it when it could be a float from the get-go.

Partly agree, most of the time this makes sense but it depends on platform and application requirements

Significant digits
The Arduino (UNO) float has only 6-7 significant digits while an int32 has 9-10, and int64 has even 18-19.
The value of these extra digits depends on the application.

Performance
The Arduino (UNO) float math is much slower than int8 or int16 math, int32 I'm not sure, int64 is slower than float. So performance wise you can gain a lot by doing part of the math in int. But that only matters if performance is a must.

Sketch size
If you can do your whole sketch in int math, you will not need the float library which saves a few KB. That can be important when your sketch approaches the limits of FLASH e.g. you have a lot of text in PROGMEM or just plain code.
If sketch size becomes a problem it is time to consider another platform.

RAM
Never investigated if doing math in float takes more heap/stack space, my asumption is it will.
If RAM becomes a problem it is time to consider another platform.

@robtillart agree with most of the points and crossed with problem you showed in example about casting few month ago thats why im always casting if it will not harm just to be sure i gonna get expected behaviour.

surepic:
@robtillart agree with most of the points and crossed with problem you showed in example about casting few month ago thats why im always casting if it will not harm just to be sure i gonna get expected behaviour.

but then, you have to know that the function expects you to type cast.

you can handle it using the operator precedence as pointed out or doing the cast inside the function.

something like this:

template <class T> void tempco(float a, float b, T &c){
  float d = sqrt(sq(a * b * (float)c )) * 0.034565; 
  c = d * sq(a/b);
}


void setup() 
{
  Serial.begin(9600);
  uint16_t someInt = 4;
  float someFloat = 4.0;
  tempco(123.0, 789.0, someInt);
  tempco(123.0, 789.0, someFloat);
  Serial.println(someInt);
  Serial.println(someFloat);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Nice but how this differs from the example in post #1?

Mean result will be the same but are there any advatanges compared to the way i did?

surepic:
Nice but how this differs from the example in post #1?

Mean result will be the same but are there any advatanges compared to the way i did?

you didn't have a function in post #1

the advantage is you don't have to perform the cast as part of the argument and you can pass either a float or a uint16 type.