I have tried to search similar questions all over the net but non was useful for me.
The nearest I got to was "If the number before the .5 is odd round up, if even round down 13.5 turns into 14 but 12.5 turns into 12".
Coming to the question:
I simply need to calculate the total amount after a meal with the formula;
total amount = mealamount+ mealamount*tip% + mealamount *tax%
I came up with this piece of code (rough only)
#include<iostream>
#include<math.h>
#include <iomanip>
using namespace std;
int main () {
double mealCost;
double total=0;
double tipp,taxx=0;
cin>>mealCost;
int tip;
cin>>tip;
tipp=(tip*mealCost)/100;
int tax;
cin>>tax;
taxx=(tax*mealCost)/100;
total=mealCost+tipp+taxx;
cout << fixed << showpoint;
cout << setprecision(2);
cout<<total<<endl;
return 0;
}
but with the set of inputs of 10.75(mealamonut), 17(tip%),5 (tax %).
the value am getting is 12.50
if I use
int totalSum = std::round(total);
its getting converted to 12
but my requirement is 13 .
How to acheive that ?
I cannot find any duplicate question to this if exists
please mention.
There are multiple ways to convert doubles to integers. You have multiple kinds of round. Check them here, which are std::round, std::lround, std::llround.
On the other hand, if what you want to do is not rounding, but elimination of fractions into one direction, then you have std::ceil that goes always higher, and std::floor, that always goes lower.
Remember to include <cmath>, not <math.h>. The latter is for C, not C++
You achieve your goal by using std::ceil() and std::floor() which is defined under cmath header file.
You are trying to always round up so you would need to use the ceil() function. Ceil is short for ceiling and there is also a floor function. Ceiling is up, floor is down, here is a c snippet to try out.
#include <stdio.h> /* printf */
#include <math.h> /* ceil */
int main ()
{
printf ( "ceil of 2.3 is %.1f\n", ceil(2.3) );
printf ( "ceil of 3.8 is %.1f\n", ceil(3.8) );
printf ( "ceil of -2.3 is %.1f\n", ceil(-2.3) );
printf ( "ceil of -3.8 is %.1f\n", ceil(-3.8) );
return 0;
}
for rounding to nearest integer math.h has nearbyint
printf ( "nearbyint (2.3) = %.1f\n", nearbyint(2.3) );
printf ( "nearbyint (3.8) = %.1f\n", nearbyint(3.8) );
Output:
nearbyint (2.3) = 2.0
nearbyint (3.8) = 4.0
Or if you want to break the default rounding behavior when .5
int totalSum= (total - floor(total) ) >= 0.5 ? ceil(total) : floor(total);
1) 10.75 + 17*10.75/100 + 5*10.75/100 = 13.115 ... how comes I can't get 12.50?
2) How do you know it's 12.50, how do you check value of result? (it may be only 12.4999..., so when it is formatted to two decimal places, it will become 12.50) Make sure you do check the actual real value (ideally in debugger or dump memory content in bytes and reconstruct the value by hand), not some string formatted intermediate.
3) this is not some production code, right? Amounts are not calculated with doubles in real financial software, as doubles are not accurate enough and you would run into all kind of hard problems with rounding to VAT, etc. If this is some real thing, you are not up to the task, ask for help some professional.
Answer:
std::round should normally do what you need. If it's ending as 12, then it's because the value is less than 12.5.
If rounded to two decimal places it shows as 12.50, you are hitting one of those "all kind of hard problems" of real financial software.
Then you should create your own round using string representation, like this example (not handling negative numbers and reinventing wheel probably):
#include <iostream>
#include <string>
/**
* Rounds floating point value in std::string type.
* Works only for positive values, and without "+" sign!
* ie. regexp ~\d*\.?\d*~ formatting.
* For malformed input the output is undefined (but should not crash).
**/
std::string financialRound(const std::string & amount) {
const size_t dotPos = amount.find_first_of('.');
if (std::string::npos == dotPos) return amount; // no decimals found
// copy whole part into temporary result
std::string result = (0 < dotPos) ? amount.substr(0, dotPos) : "0";
const size_t firstDecimalPos = dotPos + 1;
// see if there is 5 to 9 digit after dot
if (amount.size() <= firstDecimalPos) return result; // no char
const char firstDecimal = amount.at(firstDecimalPos);
if (firstDecimal < '5' || '9' < firstDecimal) return result; //not 5-9
// add 1 to the result
int patchPos = (int)result.size();
while (0 <= --patchPos) {
++result.at(patchPos);
if ('9'+1 == result.at(patchPos)) result.at(patchPos) = '0';
else break;
}
// check if additional 1 is required (add overflow)
if (-1 == patchPos) result.insert(result.begin(), '1');
return result;
}
void tryValue(const std::string & amount) {
printf("\"%s\" is rounded to \"%s\"\n", amount.c_str(), financialRound(amount).c_str());
}
int main()
{
printf("Trying normal values...\n");
tryValue("12.50");
tryValue("12.49");
tryValue(".49");
tryValue(".50");
tryValue("9.49");
tryValue("9.50");
printf("Missing decimals...\n");
tryValue("12");
tryValue("12.");
printf("Malformed...\n");
tryValue("");
tryValue("a.4");
tryValue("a.5");
tryValue("12..");
}
live demo on cpp.sh
Related
I want to round a float to maximum 4 decimals places. It mean 0.333333333 will be 0.3333, but 0.33 is still 0.33
Use the std::round() function
The C++ standard library offers functions for performing rounding. For floats, it is:
float round ( float arg );
this will round arg to the nearest integral value. Now, you want a different decimal resolution. So don't round your value, round your value times 10000, so your singles digit is now the former 0.0001 digit. Or more generally:
float my_round(
float x,
int num_decimal_precision_digits)
{
float power_of_10 = std::pow(10, num_decimal_precision_digits);
return std::round(x * power_of_10) / power_of_10;
}
Note that there may be accuracy issues, as floating-point computations and representations are only accurate to within a certain number of digits, and in my_round we have at least four sources of such inaccuracy: The power-of-10 calculation, the multiplication, the devision and the actual rounding.
Cast it into a fixed-point type
If you want to have your results rounded, with a fixed number of decimal digits, you're hinting that you don't really need the "floating" aspect of floating point numbers. Well, in this case, cast your value to a type which represents such numbers. Essentially, that would be a (run-time-variable) integer numerator and a compile-time-fixed denominator (which in your case would be 10,000).
There's an old question here on the site about doing fixed-point math:
What's the best way to do fixed-point math?
but I would suggest you consider the CNL library as something recent/popular. Also, several proposals have been made to add fixed-point types to the standard library. I don't know which one is the farthest advance, but have a look at this one: Fixed-Point Real Numbers by John McFarlane.
Back to your specific case: Fixed-point types can typically be constructed from floating-point ones. Just do that.
Here is a solution, for example:
float ret = float(round(0.333333333 * 10000)) / 10000)
You can write it as a function. Maybe there would be a better way?
Assuming you need print rounded number, this is one of a proper solutions:
cout << setprecision(4) << x << '\n';
std::setprecision documentation.
Live demo
Until more details are not provided it is impossible to provide a better answer.
Please note if you are planing to round number x then print it, it will end with big headache, since some corner cases can produce much longer results then expected.
Use _vsnprintf
I think the best solution for this is to just format the string. Because what if we don't need to output this number to the console, but save it in a std::string variable or char[] or something like that. This solution is flexible because it is the same if you output a number to the console and used the std::setprecision() function, but also returning this number to char[].
So for this I used _vsnprintf and va_list. All it does is format the string as needed, in this case float value.
int FormatString(char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
int w = _vsnprintf(buf, buf_size, fmt, args);
va_end(args);
if (buf == NULL)
return w;
if (w == -1 || w >= (int)buf_size)
w = (int)buf_size - 1;
buf[w] = 0;
return w;
}
int FormatStringFloat(char* buf, int buf_size, const void* p_data, const char* format) {
return FormatString(buf, buf_size, format, *(const float*)p_data);
}
Example
#include "iostream"
#include "string"
#define ARRAY_SIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR))))
int main() {
float value = 3.343535f;
char buf[64];
FormatStringFloat(buf, ARRAY_SIZE(buf), (void*)&value, "%.2f");
std::cout << std::string(buf) << std::endl;
return 0;
}
So by using "%.2f" we get from the 3.343535 => 3.34.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
int t;
double n;
cin>>t;
while(t--)
{
cin>>n;
double x;
for(int i=1;i<=10000;i++)
{
x=n*i;
if(x==ceilf(x))
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
For I/P:
3
5
2.98
3.16
O/P:
1
If my code is:
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
int main() {
int t;
double n;
cin>>t;
while(t--)
{
cin>>n;
double x;
for(int i=1;i<=10000;i++)
{
x=n*i;
cout<<"";//only this statement is added;
if(x==ceilf(x))
{
cout<<i<<endl;
break;
}
}
}
return 0;
}
For the same input O/P is:
1
50
25
The only extra line added in 2nd code is: cout<<"";
Can anyone please help in finding why there is such a difference in output just because of the cout statement added in the 2nd code?
Well this is a veritable Heisenbug. I've tried to strip your code down to a minimal replicating example, and ended up with this (http://ideone.com/mFgs0S):
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
float n;
cin >> n; // this input is needed to reproduce, but the value doesn't matter
n = 2.98; // overwrite the input value
cout << ""; // comment this out => y = z = 149
float x = n * 50; // 149
float y = ceilf(x); // 150
cout << ""; // comment this out => y = z = 150
float z = ceilf(x); // 149
cout << "x:" << x << " y:" << y << " z:" << z << endl;
}
The behaviour of ceilf appears to depend on the particular sequence of iostream operations that occur around it. Unfortunately I don't have the means to debug in any more detail at the moment, but maybe this will help someone else to figure out what's going on. Regardless, it seems almost certain that it's a bug in gcc-4.9.2 and gcc-5.1. (You can check on ideone that you don't get this behaviour in gcc-4.3.2.)
You're probably getting an issue with floating point representations - which is to say that computers cannot perfectly represent all fractions. So while you see 50, the result is probably something closer to 50.00000000001. This is a pretty common problem you'll run across when dealing with doubles and floats.
A common way to deal with it is to define a very small constant (in mathematical terms this is Epsilon, a number which is simply "small enough")
const double EPSILON = 0.000000001;
And then your comparison will change from
if (x==ceilf(x))
to something like
double difference = fabs(x - ceilf(x));
if (difference < EPSILON)
This will smooth out those tiny inaccuracies in your doubles.
"Comparing for equality
Floating point math is not exact. Simple values like 0.2 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. If you do a calculation and then compare the results against some expected value it is highly unlikely that you will get exactly the result you intended.
In other words, if you do a calculation and then do this comparison:
if (result == expectedResult)
then it is unlikely that the comparison will be true. If the comparison is true then it is probably unstable – tiny changes in the input values, compiler, or CPU may change the result and make the comparison be false."
From http://www.cygnus-software.com/papers/comparingfloats/Comparing%20floating%20point%20numbers.htm
Hope this answers your question.
Also you had a problem with
if(x==ceilf(x))
ceilf() returns a float value and x you have declared as a double.
Refer to problems in floating point comparison as to why that wont work.
change x to float and the program runs fine,
I made a plain try on my laptop and even online compilers.
g++ (4.9.2-10) gave the desired output (3 outputs), along with online compiler at geeksforgeeks.org. However, ideone, codechef did not gave the right output.
All I can infer is that online compilers name their compiler as "C++(gcc)" and give wrong output. While, geeksforgeeks.org, which names the compiler as "C++" runs perfectly, along with g++ (as tested on Linux).
So, we could arrive at a hypothesis that they use gcc to compile C++ code as a method suggested at this link. :)
I'm writing a program that uses brute-force to solve an equation. Unfortunately, I seem to have an error in my code somewhere, as my program stops at search = 0.19999. Here is the code:
#include <iostream>
#include <cmath>
#include <vector>
#define min -4.0
#define max 6.5
using namespace std;
double fx (double x){
long double result = cos(2*x)-0.4*x;
double scale = 0.00001;
double value = (int)(result / scale) * scale;
return value;
}
int sign (double a){
if(a<0) return -1;
if(a==0) return 0;
else return 1;
}
int main(){
vector <double> results;
double step, interval, start, end, search;
interval=(fabs(min)+fabs(max))/50;
step=0.00001;
start=min;
end=min+interval;
search=start;
while(end <= max){
if(sign(start) != sign(end)){
search=start;
while(search < end){
if(fx(search) == 0) results.push_back(search);
search=search+step;
}
}
start=end;
end=start + interval;
}
for(int i=0; i<results.size(); i++){
cout << results[i] << endl;
}
}
I've been looking at it for quite some time now and I still can't find the error in the code.
The program should check if there is a root in each given interval and, if yes, check every possibility in that interval. If it finds a root, it should push it into the results vector.
I know you already found the answer but I just spotted a problem while trying to find the bug. On line 37 you make the following comparison:
if(fx(search) == 0)
Since your fx function returns double. It's generally not advisable to test using the equal operator when dealing with double precision float numbers. Your result will probably never be exactly 0, then this test will never return true. I think you should use comparison using a maximum error margin, like this:
double maximum_error = 0.005;
if(abs(fx(search)) < maximum_error)
I think that would do the trick in your case. You may find more information on this link
Even if it's working right now, micro changes in your input numbers, CPU architecture or even compiler flags may break your program. It's highly dangerous to compare doubles in C++ like that, even though it's legal to do so.
I've just made a run through the code again and found the error.
if(sign(start) != sign(end))
was the culprit. There will be a root if the values of f(x) for start and end have different signs. Instead, I wrote that the if the signs of start and end are different, there will be a root. Sorry for the fuss.
I've been stumped on this one for days. I've written this program from a book called Write Great Code Volume 1 Understanding the Machine Chapter four.
The project is to do Floating Point operations in C++. I plan to implement the other operations in C++ on my own; the book uses HLA (High Level Assembly) in the project for other operations like multiplication and division.
I wanted to display the exponent and other field values after they've been extracted from the FP number; for debugging. Yet I have a problem: when I look at these values in memory they are not what I think they should be. Key words: what I think. I believe I understand the IEEE FP format; its fairly simple and I understand all I've read so far in the book.
The big problem is why the Rexponent variable seems to be almost unpredictable; in this example with the given values its 5. Why is that? By my guess it should be two. Two because the decimal point is two digits right of the implied one.
I've commented the actual values that are produced in the program in to the code so you don't have to run the program to get a sense of whats happening (at least in the important parts).
It is unfinished at this point. The entire project has not been created on my computer yet.
Here is the code (quoted from the file which I copied from the book and then modified):
#include<iostream>
typedef long unsigned real; //typedef our long unsigned ints in to the label "real" so we don't confuse it with other datatypes.
using namespace std; //Just so I don't have to type out std::cout any more!
#define asreal(x) (*((float *) &x)) //Cast the address of X as a float pointer as a pointer. So we don't let the compiler truncate our FP values when being converted.
inline int extractExponent(real from) {
return ((from >> 23) & 0xFF) - 127; //Shift right 23 bits; & with eight ones (0xFF == 1111_1111 ) and make bias with the value by subtracting all ones from it.
}
void fpadd ( real left, real right, real *dest) {
//Left operand field containers
long unsigned int Lexponent = 0;
long unsigned Lmantissa = 0;
int Lsign = 0;
//RIGHT operand field containers
long unsigned int Rexponent = 0;
long unsigned Rmantissa = 0;
int Rsign = 0;
//Resulting operand field containers
long int Dexponent = 0;
long unsigned Dmantissa = 0;
int Dsign = 0;
std::cout << "Size of datatype: long unsigned int is: " << sizeof(long unsigned int); //For debugging
//Properly initialize the above variable's:
//Left
Lexponent = extractExponent(left); //Zero. This value is NOT a flat zero when displayed because we subtract 127 from the exponent after extracting it! //Value is: 0xffffff81
Lmantissa = extractMantissa (left); //Zero. We don't do anything to this number except add a whole number one to it. //Value is: 0x00000000
Lsign = extractSign(left); //Simple.
//Right
**Rexponent = extractExponent(right); //Value is: 0x00000005 <-- why???**
Rmantissa = extractMantissa (right);
Rsign = extractSign(right);
}
int main (int argc, char *argv[]) {
real a, b, c;
asreal(a) = -0.0;
asreal(b) = 45.67;
fpadd(a,b, &c);
printf("Sum of A and B is: %f", c);
std::cin >> a;
return 0;
}
Help would be much appreciated; I'm several days in to this project and very frustrated!
in this example with the given values its 5. Why is that?
The floating point number 45.67 is internally represented as
2^5 * 1.0110110101011100001010001111010111000010100011110110
which actually represents the number
45.6700000000000017053025658242404460906982421875
This is as close as you can get to 45.67 inside float.
If all you are interested in is the exponent of a number, simply compute its base 2 logarithm and round down. Since 45.67 is between 32 (2^5) and 64 (2^6), the exponent is 5.
Computers use binary representation for all numbers. Hence, the exponent is for base two, not base ten. int(log2(45.67)) = 5.
Actually I am working on range expression in c++. So what I want is if I have any expression like
x<1
Then my
double getMax(...);
should return a double value that is just before 1.000 (double precision) on a number line.
I tried doing this
double getMax(double& a)
{
return (a-numeric_limits<double>::min());
}
But I am still getting same value as a in return statement.
I think C++ is converting it to nearest double in cout statement.
int main()
{
double a = 32;
cout<<scientific<<getMax(a)<<endl;
return 0;
}
output:
3.200000e+001
First of all, you need to ensure that you actually print sufficiently many digits to ensure all representable values of double are displayed. You can do this as follows (make sure you #include <iomanip> for this):
std::cout << std::scientific << std::setprecision(std::numeric_limits<double>::max_digits10) << getMax(a) << std::endl;
Secondly, numeric_limits<>::min is not appropriate for this. If your starting value is 1.0, you can use numeric_limits<double>::epsilon, which is the smallest difference from 1.0 that is representable.
However, in your code example, the starting value is 32. Epsilon does not necessarily work for that. Calculating the right epsilon in this case is difficult.
However, if you can use C++11(*), there is a function in the cmath header that does what you need std::nextafter:
#include <iostream>
#include <limits>
#include <iomanip>
#include <cmath>
double getMax(double a)
{
return std::nextafter(a,std::numeric_limits<double>::lowest());
}
int main()
{
double a = 32;
std::cout << std::scientific
<< std::setprecision(std::numeric_limits<double>::max_digits10)
<< getMax(a)
<< std::endl;
return 0;
}
I've also put it on liveworkspace.
To explain:
double nextafter(double from, double to);
returns the next representable value of from in the direction of to. So I specified std::numeric_limits<double>::lowest() in my call to ensure you get the next representable value less than the argument.
(*)See Tony D's comment below. You may have access to nextafter() without C++11.
I think you've got the right idea.
Check out Setting the precision of a double without using stream (ios_base::precision) not so much for the question, but for the examples they give of using precision. You might want to try something like printing with a precision of 53.
The way I usually see "close to but not quite" involves setting a difference threshold (typically called epsilon). In that case, you wouldn't use a getMax function, but have an epsilon used in your usage of less than. (You could do a class with the epsilon value and operator overloading. I tend to avoid operator overloading like a plague.)
Basically, you'd need:
bool lessThanEpsilon(double number, double lessThan, double epsilon)
{
return (lessThan - number >= epsilon);
}
There are other varieties, of course. Equals would check if Math.abs(number - equals) < epsilon