Input double becomes smaller without obvious reason [duplicate] - c++

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
So when I input a decimal number like 12.45, it gets decremented by 0.00001 or something that causes my function to work badly.
For example:
If x is 12.45 and div is 0.1 when watching x you can see that it becomes 12.449999999
BUT
If x is 12.455 and div is 0.01 it doesn't reduce x
double round(double x, double div){
if (div != 0){
double temp2 = 0;
int temp = x;
double dec = x - temp;
dec = dec/div;
temp = dec;
temp2 = dec-temp;
temp2 = temp2 * div;
cout << x << endl << endl;
if (temp2 >= div/2){
x+=(div-temp2);
}else{
x-=temp2;
}
cout << temp << " " << dec << " " << x << " " << temp2 << " " << div/2;
return x;
}else{
cout << "div cant be equal to zero" << endl;
}
}
I was trying to make a function that rounds up decimal numbers. I know its probably not the best to do it, but it works except the problem I described earlier.
To fix it I tried limiting decimal places at the input, didn't work. Also tried using other methods instead of using a double/integer combo without any results.
I expect the output of 12.5 when x is 12.45 and div is 0.1 but it's not working, because of the 0.000001 of the input getting lost.

Your program is going to be miss informed and will not work.
This is how floating point values are handled in programming languages as is defined in this standard.
https://en.wikipedia.org/wiki/IEEE_754#Basic_formats
They often require rounding as a result of an operation to fit within their finite representation making them difficult to compare.
https://www.boost.org/doc/libs/1_36_0/libs/test/doc/html/utf/testing-tools/floating_point_comparison.html
The issues you are seeing are artifacts of the rounding error.
https://www.itu.dk/~sestoft/bachelor/IEEE754_article.pdf

Related

setprecision(2) value not working in if statement even when the conditions are true [duplicate]

This question already has answers here:
What is the behavior of integer division?
(6 answers)
Division of two numbers always returns an integer value
(3 answers)
Closed 3 months ago.
I dont understand why setprecision(2) not working when using if else statement
I tried doing this and it displays the else statement. I dont see any problem, maybe im using setprecision() wrong? I even displayed the quotient to prove that the if statement should be the one running.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
float x = 2;
float y = 3;
float quotient, answer;
quotient = x / y;
cout << fixed << setprecision(2);
cout << quotient << " (is the answer)\n";
cout << " What is " << x << " divided by " << y << " ? ";
cin >> answer; // answer should be 0.67
if (quotient == answer)
cout << " You got the right answer! ";
else
cout << " Nice Try :( ";
return 0;
}
The line
quotient = x / y;
will assign the value of 0.0 to the variable quotient, because 2/3 is 0, using the rules of integer division. Therefore, if the user enters 0.67, this value will not compare equal to 0.0.
If you want the division 2/3 to evaluate to something like 0.6666666667, then you must make at least one of the operands a floating-point number, for example by using a cast:
quotient = static_cast<float>(x) / y;
However, even if you did this, your comparison would still not work, because the expression
cout << fixed << setprecision(2) << quotient;
will only change the way the variable quotient is printed. It will not change the actual value of the variable.
In order to round the actual value of the variable, you can use the function std::round. Note that this will only round to the nearest integer, so if you want to round to the nearest multiple of 0.01, then you will first have to multiply the number by 100 before performing the rounding operation. If you want, you can then divide the number by 100 again, to get the original number again, rounded to the nearest multiple of 0.01.
However, you should be aware that these operations may introduce slight floating-point inaccuracies. For this reason, it may be better to not require an exact match in the comparison
if (quotient == answer)
but to consider a deviation of up to 0.01 to still be considered a match. You can do this for example by changing the expression to this:
if ( std::abs( quotient - answer ) < 0.01 )
Note that you will have to #include <cmath> in order to use std::round and std::abs.

Am I doing double to float conversion here

const double dBLEPTable_8_BLKHAR[4096] = {
0.00000000000000000000000000000000,
-0.00000000239150987901837200000000,
-0.00000000956897738824125100000000,
-0.00000002153888378764179400000000,
-0.00000003830892270073604800000000,
-0.00000005988800189093979000000000,
-0.00000008628624126316708500000000,
-0.00000011751498329992671000000000,
-0.00000015358678995269770000000000,
-0.00000019451544774895524000000000,
-0.00000024031597312124120000000000,
-0.00000029100459975062165000000000
}
If I change the double above to float, am I doing incurring conversion cpu cycles when I perform operations on the array contents? Or is the "conversion" sorted out during compile time?
Say, dBLEPTable_8_BLKHAR[1] + dBLEPTable_8_BLKHAR[2] , something simple like this?
On a related note, how many trailing decimal places should a float be able to store?
This is c++.
Any good compiler will convert the initializers during compile time. However, you also asked
am I incurring conversion cpu cycles when I perform operations on the array contents?
and that depends on the code performing the operations. If your expression combines array elements with variables of double type, then the operation will be performed at double precision, and the array elements will be promoted (converted) before the arithmetic takes place.
If you just combine array elements with variables of float type (including other array elements), then the operation is performed on floats and the language doesn't require any promotion (But if your hardware only implements double precision operations, conversion might still be done. Such hardware surely makes the conversions very cheap, though.)
Ben Voigt answer addresses your question for most parts.
But you also ask:
On a related note, how many trailing decimal places should a float be able to store
It depends on the value of the number you are trying to store. For large numbers there is no decimals - in fact the format can't even give you a precise value for the integer part. For instance:
float x = BIG_NUMBER;
float y = x + 1;
if (x == y)
{
// The code get here if BIG_NUMBER is very high!
}
else
{
// The code get here if BIG_NUMBER is no so high!
}
If BIG_NUMBER is 2^23 the next greater number would be (2^23 + 1).
If BIG_NUMBER is 2^24 the next greater number would be (2^24 + 2).
The value (2^24 + 1) can not be stored.
For very small numbers (i.e. close to zero), you will have a lot of decimal places.
Floating point is to be used with great care because they are very imprecise.
http://en.wikipedia.org/wiki/Single-precision_floating-point_format
For small numbers you can experiment with the program below.
Change the exp variable to set the starting point. The program will show you what the step size is for the range and the first four valid numbers.
int main (int argc, char* argv[])
{
int exp = -27; // <--- !!!!!!!!!!!
// Change this to set starting point for the range
// Starting point will be 2 ^ exp
float f;
unsigned int *d = (unsigned int *)&f; // Brute force to set f in binary format
unsigned int e;
cout.precision(100);
// Calculate step size for this range
e = ((127-23) + exp) << 23;
*d = e;
cout << "Step size = " << fixed << f << endl;
cout << "First 4 numbers in range:" << endl;
// Calculate first four valid numbers in this range
e = (127 + exp) << 23;
*d = e | 0x00000000;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
*d = e | 0x00000001;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
*d = e | 0x00000002;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
*d = e | 0x00000003;
cout << hex << "0x" << *d << " = " << fixed << f << endl;
return 0;
}
For exp = -27 the output will be:
Step size = 0.0000000000000008881784197001252323389053344726562500000000000000000000000000000000000000000000000000
First 4 numbers in range:
0x32000000 = 0.0000000074505805969238281250000000000000000000000000000000000000000000000000000000000000000000000000
0x32000001 = 0.0000000074505814851022478251252323389053344726562500000000000000000000000000000000000000000000000000
0x32000002 = 0.0000000074505823732806675252504646778106689453125000000000000000000000000000000000000000000000000000
0x32000003 = 0.0000000074505832614590872253756970167160034179687500000000000000000000000000000000000000000000000000
const double dBLEPTable_8_BLKHAR[4096] = {
If you change the double in that line to float, then one of two things will happen:
At compile time, the compiler will convert the numbers -0.00000000239150987901837200000000 to the float that best represents them, and will then store that data directly into the array.
At runtime, during the program initialization (before main() is called!) the runtime that the compiler generated will fill that array with data of type float.
Either way, once you get to main() and to code that you've written, all of that data will be stored as float variables.

C++ Money Class - storing and rounding cents

thanks in advance.
I'm writing a C++ assignment for class where we're creating our own money/currency class. I'm having trouble figuring out why my passing of a float isn't giving me enough precision.
Implementation:
private:
long int DOLLARS;
short int CENTS;
Currency::Currency(float tmpMoney)
{
// cout << "tmpMoney is: " << tmpMoney << endl;
int tmpDollar;
float tmpCent;
tmpDollar = static_cast<int>(tmpMoney);
tmpCent = (tmpMoney-tmpDollar)*100;
DOLLARS = tmpDollar;
CENTS = tmpCent;
}
Main Program:
Currency c1(2342.59);
Currency c2(2342.515); // there is no half cent coin, round it to 2342.52
If I output 'tmpMoney' it just gives me (for c2) 2345.51.
I'm not sure how to round .515 if the value doesn't even go that far.
It's a bad idea to make a currency type be constructible from floating-point type.
7 decimal digits is in general beyond float precision. You can still get desired output by:
float tmpMoney = 2342.515;
cout << setprecision(7) << tmpMoney << endl;
// 2342.515
But the internal representation is far from perfect:
cout << setprecision(10) << tmpMoney << endl;
// 2342.514893
If the number is large enough, you'll lose more:
float tmpMoney = 123456789.12;
cout << setprecision(12) << tmpMoney << endl;
// 123456792
So you may decide to use double instead, but you should be really careful because for large enough numbers you'll get the same errors:
double tmpMoney = 3333333333333333.42; // 17 digits
cout << setprecision(18) << tmpMoney << endl;
// 3333333333333333.5
If there is a chance that you'll have such numbers, don't initialize Currency with double either.
I would advise you to have just a constructor like Currency(int dollars, int cents).
You can also check this question for some insights.
#include <cmath>
CENTS = round(tmpCent);
Due to floating point representation, this may not always give the right result. The closest you can get is have a margin of error epsilon, say
#define EPS 0.000001
then you can do
CENTS = round(tmpCent + EPS);
Note that this will accept values that are represented as 0.499999 <= x < 0.5
And it's preferable to use double and not float to keep the precision as close as possible.

How to display a floating point result of a division of two integers? [duplicate]

This question already has answers here:
Dividing 1/n always returns 0.0 [duplicate]
(3 answers)
Closed 8 years ago.
I have a problem with displaying and keeping any floating number or double or long or floating type this is the code :
int sd, n;
float d;
d=n/sd.capacity();
cout << d.toFloat() << endl;
cout << n << " / " << sd.capacity() << " = " << d << endl;
In the output I have d equal to 0 everytime, sd.capacity() and n are never 0, so all the time n is lower than sd.capacity value, d = 0 but it should never 0. The variable d does not contain anything but 0.
int/int results into int. So this does a problem.
You need to have atleast one of the operands as float.
Since, you are telling that n always < than sd.capacity(), so n/sd.capacity() in int division always gives 0.
I suppose you should do,
d= (float)n / (float)sd.capacity();
Does this solve it?

How to set 3 digits after comma

Well, basically I was using setprecision(3), but that is rounding up the last number, for example if we do like this -
double x = 5;
x = (double) x / 3;
cout << fixed << setprecision(3) << x << endl;
It will show 1.667
But, if we do it with calculator, it will show - 1.666666666...67
So basically, what I mean is, is there any chance to output in file, just the first 3 digits after the comma, and not to round it up?
1.666666666...67 rounded to three decimal places is 1.667
If you just want to truncate the output then send it to a string with strstream, search the string for the position of "." and truncate the string 3 places beyond that
Or if you simply want to always round down, multiply the result by 1000, use floor() to round down and then divide by 1000.0 again.
A cast to long truncates the fraction part :
int main()
{
double x;
x= -100.666666666666666;
x = static_cast<double> ( static_cast<long>(x * 1000) )/1000;
cout << x << endl;
}
We could use floor(double) from cmath, which is more preferable, but it's rounds negatives to negative side either.
cout << fixed << setprecision(3) << double(int(x*1000))/1000 << endl;
we use int() to truncate the tailing digits.