-3

I need to convert and round F to C. My function is simply:

return (int)((((float)5 / (float)9) * (f - 32)) + 0.5)

But if I input 14 f, I get back -9 c, instead of -10 c.

J Doe.
  • 299
  • 3
  • 13
  • you need to use rounding, not truncation. – Daniel A. White Sep 15 '17 at 19:38
  • 1
    See: https://stackoverflow.com/a/4890488/1531971 –  Sep 15 '17 at 19:39
  • @jdv are you saying that `(float)5 / (float)9` is integer division? – Weather Vane Sep 15 '17 at 19:39
  • @WeatherVane, no, of course not. I glossed over the casts on initial read, but I knew this had been discussed many times before, and there were other things of interest in there. As another comment suggests, casting in this manner is totally awkward, so my eyes were looking for the decimal points. (Or point, given how C works.) –  Sep 15 '17 at 19:41
  • Truncation should work as well as rounding when its cast back to an int. If not please tell me why instead of just saying don't do it. – J Doe. Sep 15 '17 at 19:42
  • 1
    Instead of the awkward `(float)5` you could use `5.f`. Or `5.0f`. – Eugene Sh. Sep 15 '17 at 19:42
  • 2
    Wouldn't the `+0.5` have to be changed to `-0.5` in the case where `f<32`? – AntonH Sep 15 '17 at 19:44
  • Why are you adding 0.5 in the end? I don't believe that is supposed to be in the conversion formula. – Alien13 Sep 15 '17 at 19:44
  • @Alien13 for rounding. If it's 9.7, it should be rounded up to 10. But with a cast to int, it will be rounded down, always. But adding 0.5, it will round up when the decimal value if bigger than 0.5. – AntonH Sep 15 '17 at 19:45
  • 1
    Adding 0.5 to round works properly only for *positive* numbers. – Steve Summit Sep 15 '17 at 19:46
  • There's a standard `round()` function now, that should do the right thing. – Steve Summit Sep 15 '17 at 19:48
  • I am on vxWorks platform. Please don't ask me why, but even including `math.h` will not allow usage of `round` or `roundf` and not even my senior devs understand why. – J Doe. Sep 15 '17 at 19:50
  • @JDoe. How does it "not allow usage". A compile time error/warning, a linker problem? – chux - Reinstate Monica Sep 15 '17 at 20:06
  • @chux I include `math.h` and any function I try to use is undefined. Mind you all functions appear to be externs, and there is a warning that some functions may not work on specific architectures. So I gave up on it. – J Doe. Sep 15 '17 at 20:07
  • 2
    @JDoe.: you may need to explicitly link the math library in addition to using the `math.h` header. With most gcc implementations you would add `-lm` to the command line to link the math library. – John Bode Sep 15 '17 at 20:12

5 Answers5

2

C has a nice function lround() to round and convert to an integer.

The lround and llround functions round their argument to the nearest integer value, rounding halfway cases away from zero, regardless of the current rounding direction. C11dr §7.12.9.7 2

#include <math.h>

return lround(5.0/9.0 * (f - 32));

The +0.5 and than cast to int has various troubles with it. It "rounds" incorrectly for negative values and rounds incorrectly for various edge case when x +0.5 is not exact.

Use the <math.h> round functions, rint(), round(), nearbyint(), etc) best tools in the shed.


OP comment about needing a vxWorks solution. That apparently has iround to do the job.


For a no math.h nor double solution:
Use (a + sign(a)*b/2)/b idiom. After offsetting by 32 degrees F, we need c = irounded(5*f/9) or c = irounded(10*f/18).

int FtoC(int f) {
  f -= 32;
  if (f < 0) {
    return (2*5*f - 9)/(2*9);
  }
  return (2*5*f + 9)/(2*9);
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • I don't have access to this function on vxWorks platform – J Doe. Sep 15 '17 at 19:58
  • @JDoe. The post does not detail the limitation - if important, that limitation should have been part of the original post. Could use [iround](http://www.vxdev.com/docs/vx55man/vxworks/ref/mathALib.html#iround). Is it as if _vxWorks_ has supplied the perfect function for you. – chux - Reinstate Monica Sep 15 '17 at 19:59
  • I would love to, but I have given up on any function in `math.h` as they will never be defined. It may be an architecture limitation (as the comments in the file say). It's mind boggling, but not a single math.h function is used in the millions of lines of code in our system. – J Doe. Sep 15 '17 at 20:05
  • @JDoe. What is the type of `f`: an integer or floating point? – chux - Reinstate Monica Sep 15 '17 at 20:07
  • 1
    It is an `int` type – J Doe. Sep 15 '17 at 20:08
1
((14 - 32) * 5.0) / 9.0 = -10.0
-10.0 + 0.5 = -9.5
(int)(-9.5) = -9
Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
1

Adding 0.5 for rounding purposes will only work when the result of the calculation of f - 32 is positive. If the result is negative, it has to be changed to -0.5.

You could change your code to this:

int roundVal = (f < 32) ? -0.5 : 0.5;
return (int)((((float)5 / (float)9) * (f - 32)) + roundVal);
AntonH
  • 6,359
  • 2
  • 30
  • 40
0

Everyone's

"Int() doesn't function correctly in the negative region of the number line"

is completely and utterly WRONG, and quite disgusting! We programmers should know and understand the concept of "the number line"!

Int(9.5) == 10          => true
Int(-9.5) == -9         => true

Lets say we have a dataset, that coincidently is something point 5, and is a linear system. Keep in mind that this is matlab syntax, to me programming is programming, so entirely applicable in any language.

x = [-9.5:1:9.5] % -9.5 to 9.5 at increments of 1 -9.5 -8.5 -7.5 ..... 9.5

% Now we need a function Int(), and lets say it rounds to the nearest,
% as y'all say it should be: "direction of the sign".  MATLAB doesn't
% have
Int()... that I know of.

function INTEGER = Int_stupid(NUMBER)
    POL = NUMBER / abs(NUMBER)  % Polarity multiplier
    VALUE_temp = NUMBER + (POL * 0.5)   % incorrectly implemented 
                                        % rounding to the nearest
        % A number divided by it's absolute value is 1 times it's
        % polarity
        % ( -9.5 / abs( -9.5 ) ) = -1
        % ( 9.5 / abs( 9.5 ) ) = 1
end

function INTEGER = Int(NUMBER)  % how every other Int function works
    VALUE_temp = NUMBER + 0.5   % correctly implemented rounding 
                                % to the nearest
end

% Now we need the whole dataset rounded to the "nearest direction of the sign"

x_rounded = Int_stupid(x) => x = [-10, -9, -8,... -1, 1, 2...] % notice how there is no 0, there is % discontinuity in this bad rounding.

Bad Rounding discontinuity

                            % Notice that in the plot there is a zig, 
                            % or zag, in my PERFECT LINEAR SYSTEM.

Good & Bad Rounding with RAW

                            % Notice the two parallel lines with no         
                            % defects representing the RAW linear 
                            % system, and the parallel correctly 
                            % rounded => floor( x + 0.5 )

Rounded to the nearest data, if done correctly, will parallel the actual data.

Sorry for my anger, and programmatic insults. I expect experts to be experts, that don't sell completely incorrect information. And if I do the same, I expect the same humiliation from my peers => YOU.

References ( for 2nd grade how to round numbers ): %_https://math.stackexchange.com/questions/3448/rules-for-rounding-positive-and-negative-numbers %_https://en.wikipedia.org/wiki/IEEE_754#Rounding_algorithms

JustBaron
  • 2,319
  • 7
  • 25
  • 37
  • to clean up the source: " return (int) ( (float)( (f - 32) * 5 / 9 ) ) ", because the preceding (float), or (int) will cover all that follows. Also math people seem to like the multiplier "(f-32)" before the fraction, so it matches NUMBER * NUMERATOR / DENOMINATOR. You've got wayyyy too many parenthesis. I think nobody just likes tracking open and closed parenthesis. – Michael 'Hitch' E. Hitchcock Sep 16 '17 at 21:38
  • This BIGGER problem, "Int() doesn't round negative numbers correctly", even though it does, reminds me of my Navy Submarine School days. People only listen to idiots, and not to people who actually know. So, the answers in the back of the book become incorrect, because the teacher didn't understand "Order of Operations". My math, is never wrong at point of sale. Just a newbie here, I don't know algebra, calculus, trigonometry, or how to take a measurement. And of course, those things are just useless in programming.... especially in more complex systems... – Michael 'Hitch' E. Hitchcock Sep 16 '17 at 22:41
  • oops, sorry! cleanup (with proper rounding to the nearest) should be: return (int) (((F - 32.0f) * 5.0f/9.0f) + 0.5f); – Michael 'Hitch' E. Hitchcock Sep 17 '17 at 02:38
0

It sounds like you have two problems:

  1. The number you're trying to round is negative, meaning that the standard trick of adding 0.5 goes the wrong way.

  2. Standard rounding functions like round() are for some reason denied to you.

So just write your own:

double my_round(double x, double to_nearest)
{
    if(x >= 0)
        return (int)(x / to_nearest + 0.5) * to_nearest;
    else
        return (int)(x / to_nearest - 0.5) * to_nearest;
}

Now you can write

return (int)my_round(5./9. * (f - 32), 1.0);
Steve Summit
  • 45,437
  • 7
  • 70
  • 103