This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.
double bround2dec(double d)
{
// save sign
int sgn = (d < 0.)? -1 : 1;
double dabs = d * sgn;
// convert to 64 bit integer and factor 1000
long long ll1000 = (long long)(dabs * 1000);
// get last digit
int rc = (int) ll1000%10;
// if the first decimal digit which decides whether to round up or down is not 5
// we simply can round by adding 5 and cut by doing integer rounding
if (rc != 5)
return ((ll1000 + 5)/1000.) * sgn;
// if coming here we extract the digit which was subject of being rounded
int rr = (int) ((ll1000-rc)/10)%10;
// if the digit is odd we round up else we round down
return ((rr+1)%2 == 0)? ((ll1000 + 5)/1000.) * sgn : ((ll1000-5)/1000.) * sgn;
}
// you can use it like
#include <sstream>
#include <iostream>
#include <string>
....
double d1 = 20.225;// 225.885;
double d2 = 20.235;// -0.065;
std::ostringstream oss;
// std::ios::fixed means that the number of decimal digits in the fraction given by the setprecison was fixed
// otherwise the precision means the number of significant digits of the decimal number
oss << d1 << " was rounded to " << std::setiosflags( std::ios::fixed ) << std::setprecision(2) << bround2dec(d1) << " "
<< d2 << " was rounded to " << std::setiosflags( std::ios::fixed ) << std::setprecision(2) << bround2dec(d2);
std::string s = oss.str();
Can you explain the method?the explanation was given in the link phoffric has posted:
The float data type can represent all whole numbers, but no fractions, within the range 8388608.0f to 16777216.0f. Any float numbers which are larger than 8388607.5f are whole numbers, and no rounding will be necessary. Adding 8388608.0f to any non-negative float which is smaller than that will yield a whole number which will be rounded according to the current rounding mode (typically round-half-to-even). Subtracting 8388608.0f will then yield a properly-rounded version of the original (assuming it was in a suitable range).
Is it because my system is 32 bit?
return ((ll1000 + 5)/1000.) * sgn;
return ((ll1000 + 5)/1000) * sgn;
That does not work either.
#include <limits.h>
double bround(double d)
{
// save the sign info
int sgn = (d < 0.)? -1 : 1;
// make it positive
double dabs = d * sgn;
// convert to 64-bit integer
// note a 64-bit integer has a range from -2^63 to 2^63
// while a double is from approximately -1.8 × 10^308 to 1.8 × 10^308
// if that is an issue you may not use the bround function
if (d < (double)(LLONG_MIN/1000) || d > (double)(LLONG_MAX/1000))
{
return d;
}
// convert to 64-bit integer with 3 fractional digits
long long ll1000 = (long long)(dabs * 1000);
// extract last digit
int rc = (int) ll1000%10;
// if not 5 we can do a 'normal rounding' ...
if (rc != 5)
{
// ... by adding 5 to the long long and do an integer division by 10
// so for 0 to 4 we get a maximum of 9 and therefore round down and
// for 6 to 9 we pass the next 10 boundary and round up
// by dividing with 100. we get a double with 2 decimals
return ((ll1000 + 5)/10)/100. * sgn;
}
// extract the forelast digit
int rr = (int) ((ll1000-rc)/10)%10;
// check if even or odd by using modulo 2
// and either add 5 for odd digits or subtract 5 for even digits
// what both means to round to the nearest even integer
return ((rr+1)%2 == 0)? ((ll1000 + 5)/10)/100. * sgn : ((ll1000-5)/10)/100. * sgn;
}
Finally, instead of cout, how do you store your output in a double variable with precision 2?
double bround2dec(double d)
{
// save sign
int sgn = (d < 0.)? -1 : 1;
double dabs = d * sgn;
char buffer[32];
double retVal =0.00;
// convert to 64 bit integer and factor 1000 - This could be an in parameter depending on scale
long long ll1000 = (long long)(dabs * 1000);
// get last digit
long long rc = (long long) ll1000%10;
// if last digit is 5 and before it is even, subtract 5, else add 5
// so 20.905 = 20.90 and 20.915 = 20.92
if (rc == 5)
{
if((ll1000-5)/10%10%2 == 0)
retVal = (ll1000 -5)/1000.* sgn;
else
retVal = (ll1000+5)/1000.* sgn;
}
else
retVal = dabs* sgn;
sprintf(buffer, "%0.2f", retVal);
return atof(buffer);
}
I tested out in my app and seems to work for large numbersAre you are experiencing a similar issue? Get a personalized answer when you ask a related question.
Have a better answer? Share it in a comment.
Open in new window
Testing 20.225
20.22
Testing 20.235
20.24
https://stackoverflow.com/questions/32746523/ieee-754-compliant-round-half-to-even