tags:

views:

190

answers:

6

I need a C rounding function which rounds numbers like MATLAB's round function. Is there one? If you don't know how MATLAB's round function works see this link:

MATLAB round function

I was thinking I might just write my own simple round function to match MATLAB's functionality.

Thanks,

DemiSheep

+1  A: 

No, C (before C99) doesn't have a round function. The typical approach is something like this:

double sign(double x) { 
    if (x < 0.0)
        return -1.0;
    return 1.0;
}

double round(double x) { 
    return (long long)x + 0.5 * sign(x);
}

This rounds to an integer, assuming the original number is in the range that can be represented by a long long. If you want to round to a specific number of places after the decimal point, that can be a bit harder. If the numbers aren't too large or too small, you can multiply by 10N, round to an integer, and divide by 10N again (keeping in mind that this may introduce some rounding errors of its own).

Jerry Coffin
Erm... C *does* have a round() function.
DevSolar
C (at least c99) surely has round/roundf/roundl - as well as lrint/llrint and similar.
nos
C99 does -- but C89/90 most assuredly does *not*. Given the number of implementations that are still C89/90, knowing how to do it on your own is still quite useful.
Jerry Coffin
Alas, squire, time hath moveth on. When someone asks a C question, I assume he's referring to a halfways up-to-date implementation.
DevSolar
Alas knave, time moveth slowly. Based on actual implementations, assuming anybody's using C99 is pretty silly. Neither of the "big 2" (Gnu and Microsoft) is even *close* to full compliance with C99. pcc is in the paradoxical position of implementing virtually all new C99 features, but still missing lots of crucial C89/90 features. The only reasonably complete implementation of C99 easily available is Comeau with Dinkumware's C99 library. I've been a Comeau user for years, but I'm well aware of how few others are.
Jerry Coffin
From that standpoint, we shouldn't be answering C++ questions at all because there is only *one* implementation (Comeau, again, or rather its EDG frontend) that's implementing C++ (98) completely. ('export'... my pet peeve.) I have somewhat of a problem with blanket statements like "given the number of implementations..." or "not even *close* to full compliance". Can you say something on the status of rounding support? If not, I feel your statements are misleading.
DevSolar
@DevSolar: It depends on the library, not the compiler. The one Microsoft distributes doesn't. With Gnu, the library you get depends on the port you use. For example, on Windows cygwin does have rounding support, but MinGW doesn't (or didn't when I last looked anyway). On other systems, the names change but the situation doesn't -- at least from what I've seen, there's probably about a 40:60 split between having it and not.
Jerry Coffin
@DevSolar: as far as answering C++ question goes, I take about the same position as I do with this: yes, `export` is in the standard, but no, I don't assume that most people have it. If I mention `export`, I usually say something like: "In theory, you should use `export`, but most C++ implementations don't have that, so you need to put all template definitions in headers."
Jerry Coffin
Still, the statement "C doesn't have a round function" is plain wrong, and misleading.
DevSolar
@DevSolar: That's true -- corrected.
Jerry Coffin
+7  A: 

This sounds similar to the round() function from math.h

These functions shall round their argument to the nearest integer value in floating-point format, rounding halfway cases away from zero, regardless of the current rounding direction.

There's also lrint() which gives you an int return value, though lrint() and friends obey the current rounding direction - you'll have to set that using fesetround() , the various rounding directions are found here.

nos
Well, `round()` also does obey `fesetround()`, as well as a multitude of other functions that cover any combination of parameter and return type. `round()` is only special in sofar as that it's the only function from the bunch that doesn't have a 'l' or 'f' appended or prepended...
DevSolar
The docs explicitly state that round/roundf/roundl does not care for the current rounding direction. math function without a f or l suffix generally takes a double as argument.
nos
Whoa. Thank you, I missed that little detail (of round/roundf/roundl not honoring the <fenv.h> settings.)
DevSolar
+1  A: 

If I'm not mistaken you are looking for something like floor and ceil and you shall find them in <math.h>

rano
+2  A: 

Check out the standard header <fenv.c>, specifically the fesetround() function and the four macros FE_DOWNWARD, FE_TOWARDZERO, FE_TONEAREST and FE_UPWARD. This controls how floating point values are rounded to integers. Make sure your implementation (i.e., C compiler / C library) actually support this (by checking the return value of fesetround() and the documentation of your implementation).

Functions honoring these settings include (from <math.h>):

  • llrint()
  • llrintf()
  • llrintl()
  • lrint()
  • lrintf()
  • lrintl()
  • rint()
  • rintf()
  • rintl()
  • llround()
  • llroundf()
  • llroundl()
  • lround()
  • lroundf()
  • lroundl()
  • nearbyint()
  • nearbyintf()
  • nearbyintl()

depending on your needs (parameter type and return type, with or without inexact floating point exception).

NOTE: round(), roundf() and roundl() do look like they belong in the list above, but these three do not honor the rounding mode set by fesetround()!!

Refer to your most favourite standard library documentation for the exact details.

DevSolar
+1  A: 

If there isn't a round() function in the standard library, you could, if dealing with floating-point numbers, arbitrarily evaluate each value, analyze the number in the place after the place you want to round to, check to see if it's greater, equal-to, or less-than 5; Then, if the value is less than 5, you can floor() the number you're ultimately looking at. If the value of the digit after the place you're rounding to is 5 or greater, you can proceed to having the function floor() the number being evaluated, then add 1.

I apologize for any inefficiency tied to this.

Mr_Spock
I was thinking of doing something like this. If the value is greater than .5, wouldn't I just do ceil()? How would I check the decimal place? Maybe cut off the whole number then check if the decimal number is greater or less than .5?
DemiSheep
If you do something like break a number like 5.321 into an array that holds 4 elements, each containing a number within your 5.321 number, then you could, if you wanted to round to the nearest whole number, evaluate 3 alone. Look up "arbitrary precision arithmetic." D.E Knuth wrote some text on the subject in "The Art of Computer Programming." I believe it was Volume 2 where he spoke of it. Anyway, you'd basically convert 5.321 into a string, then treat each character (excluding the decimal point) as its own value (first you'd convert each character into a number using something like atoi()).
Mr_Spock
This is about the worst way you could go about it, especially since there *are* plenty of options in the standard library. (You *could* have checked before writing the answer.) The scary thing is that this answer actually got accepted...
DevSolar
A: 

The documentation specifies

Y = round(X) rounds the elements of X to the nearest integers.

Not the plural: as per regular MATLAB operations, it operates on all elements of a matrix. The C equivalents posted above only deal with a single value at once. If you can use C++, check out Valarray. If not, then good ol' for loop is your friend.

André Caron