Incorrect result with cpp_dec_float division - boost

I'm having a problem with boost cpp_dec_float division producing wrong results.
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
int main()
{
using namespace boost::multiprecision;
using namespace std;
cpp_dec_float_50 a = 15; // exactly 5 * 3
cpp_dec_float_50 b = 3;
cpp_dec_float_50 c = a / b; // should be exactly 5
cpp_dec_float_50 d = 5;
cout << setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10);
cout << "c: " << c << endl;
cout << "d: " << d << endl;
cout << "c == d: " << (c == d ? "true" : "false") << endl;
return 0;
}
This produces
c: 4.999999999999999999999999999999999999999999999999999999999999999999999995
d: 5
c == d: false
I saw this question which discusses it for a fractional result. While some comments there were trying to explain it as an effect of truncation, that was not convincing IMO.
And in my case, all values, including the result, are integers, so if there is a decimal arithmetic performed, no truncation should happen.
Any ideas to make boost produce the correct/expected results?

Related

Why is my Grid Traveler Memoization still sticking?

I'm currently working on implementing memoization into the Grid Traveler problem. It looks like it should work, but it's still sticking on bigger cases like (18,18). Did I miss something, or are maps not the right choice for this kind of problem?
P.S. I'm still very new at working with maps.
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
uint64_t gridTravMemo(int m, int n, unordered_map<string, uint64_t>grid)
{
string key;
key = to_string(m) + "," + to_string(n);
if (grid.count(key) > 0)
return grid.at(key);
if (m == 1 && n == 1)
return 1;
if (m == 0 || n == 0)
return 0;
grid[key] = gridTravMemo(m-1, n, grid) + gridTravMemo(m, n-1, grid);
return grid.at(key);
}
int main()
{
unordered_map<string, uint64_t> gridMap;
cout << gridTravMemo(1, 1, gridMap) << endl;
cout << gridTravMemo(2, 2, gridMap) << endl;
cout << gridTravMemo(3, 2, gridMap) << endl;
cout << gridTravMemo(3, 3, gridMap) << endl;
cout << gridTravMemo(18, 18, gridMap) << endl;
return 0;
}
The point of memorized search is to optimize running time by returning any previous values that you have calculated. This way, instead of a brute force algorithm, you can reach a runtime of O(N*M).
However, you are passing your unordered_map<string, uint64_t>grid as a parameter for your depth-first search.
You are calling grid[key] = gridTravMemo(m-1, n, grid) + gridTravMemo(m, n-1, grid); This means that your search is splitting into two branches. However, the grid in these two branches are different. This means that the same state can be visited in two separate branches, leading to a runtime more like O(2^(N*M)).
When you're testing an 18x18 grid, this definitely will not run quickly enough.
This is relatively easy to fix. Just declare grid as a global variable. This way its values can be used between different branches.
Try something like this:
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
unordered_map<string, uint64_t> grid;
uint64_t gridTravMemo(int m, int n)
{
string key;
key = to_string(m) + "," + to_string(n);
if (grid.count(key) > 0)
return grid.at(key);
if (m == 1 && n == 1)
return 1;
if (m == 0 || n == 0)
return 0;
grid[key] = gridTravMemo(m-1, n) + gridTravMemo(m, n-1);
return grid.at(key);
}
int main()
{
cout << gridTravMemo(1, 1) << endl;
grid.clear()
cout << gridTravMemo(2, 2) << endl;
grid.clear()
cout << gridTravMemo(3, 2) << endl;
grid.clear()
cout << gridTravMemo(3, 3) << endl;
grid.clear()
cout << gridTravMemo(18, 18) << endl;
return 0;
}

Possible rounding error? C++

I'm still very new to c++, so forgive me if this should is an ignorant question. The purpose of this short code is to calculate a monthly car payment based on 6 user inputs.
Using these inputs, 623.72 is output, however I was expecting 626.81
Inputs, in order: 20000,
0.06,
1000,
100,
0.07,
36.
Can anyone shed any light on why my answer is slightly off? Am I running into a rounding error? Am I rounding in the wrong place or using a wrong variable type?
Thanks!
The formula for monthly payment is broken down into steps which made it easier to write. It's based off this formula:
monthly_payment =
Final_price_minus_downpayment * ( (monthly_rate * (1 + monthly_rate)^num_months / (1 + monthly_rate)^num_months - 1 )
#include <iostream>
#include <iomanip>
#include <cmath>
using std::cout;
using std::cin;
using std::endl;
using std::pow;
using std::fixed;
using std::setprecision;
int main() {
//Initializing the 6 user inputs
double carPrice;
double salesTaxRate;
double downPayment;
double titleAndFees;
double yearlyInterestRate;
double loanDuration;
//Getting the 6 user inputs
cin >> carPrice;
cin >> salesTaxRate;
cin >> downPayment;
cin >> titleAndFees;
cin >> yearlyInterestRate;
cin >> loanDuration;
//Calculate the monthly Payment
double salesTax = carPrice * salesTaxRate;
double totalPrice = carPrice + salesTax;
double finalPriceMinusDown = totalPrice - downPayment;
double monthlyInterestRate = yearlyInterestRate / 12.0;
//Formula broken down into steps
double step1 = pow((1+monthlyInterestRate),loanDuration);
cout << step1 << endl;
double step2 = monthlyInterestRate * step1;
cout << step2 << endl;
double step3 = step1 - 1;
cout << step3 << endl;
double step4 = step2 / step3;
cout << step4 << endl;
double step5 = finalPriceMinusDown * step4;
cout << step5 << endl;
double monthlyPayment = step5;
//cout << "The monthly payment is: ";
cout << fixed << setprecision(2) << monthlyPayment;
}

casting double to signed vs unsigned integer

It seem that the MSVC Compiler treats signed and unsigned overflow differnetly. When casting a double value that exceeds the maximum integer value, the result is the smallest possible integer value (always the same). When casting to unsigned int, the cast produces an overflow as expected (maximum unsigned int value + 1 produces 0, maximum unsigned int + 2 produces 1, ...)
Can someone explain the behaviour of the compiler, or is it a bug?
Tested compilers MSVC 10 and 14
#define BOOST_TEST_MODULE Tests
#include <boost/test/unit_test.hpp>
#include <climits>
#include <iostream>
BOOST_AUTO_TEST_CASE(test_overflow_signed) {
double d_int_max_1 = INT_MAX + 1.; //2147483647 + 1
double d_int_max_2 = INT_MAX + 2.; //2147483647 + 2
BOOST_CHECK((int)(2147483648.) != (int)(2147483649.)); //succeeds (overflows to -2147483648 and -2147483647)
BOOST_CHECK((int)(d_int_max_1) != (int)(d_int_max_2)); //fails (both values overflow to -2147483648)
std::cout << "(int)(2147483648.) == " << (int)(2147483648.) << std::endl; //-2147483648
std::cout << "(int)(2147483649.) == " << (int)(2147483649.) << std::endl; //-2147483647
std::cout << "(int)(d_int_max_1) == " << (int)(d_int_max_1) << std::endl; //-2147483648
std::cout << "(int)(d_int_max_2) == " << (int)(d_int_max_2) << std::endl; //-2147483648
}
BOOST_AUTO_TEST_CASE(test_overflow_unsigned) {
double d_int_max_1 = UINT_MAX + 1.;//4294967295 + 1
double d_int_max_2 = UINT_MAX + 2.;//4294967295 + 2
//BOOST_CHECK((unsigned int)(4294967296.) != (unsigned int)(4294967297.)); //compiler fails (!= truncation of constant value)
BOOST_CHECK((unsigned int)(d_int_max_1) != (unsigned int)(d_int_max_2)); //succeeds (overflows to 0 and 1)
std::cout << "(unsigned int)(d_int_max_1) == " << (unsigned int)(d_int_max_1) << std::endl; //0
std::cout << "(unsigned int)(d_int_max_2) == " << (unsigned int)(d_int_max_2) << std::endl; //1
}
[conv.fpint]/1 A prvalue of a floating point type can be converted to a prvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be
represented in the destination type.
Emphasis mine. Since the behavior is undefined, any outcome whatsoever is correct.

OpenCV perspectiveTransform broken function

Im trying to use perspectiveTransform but I keep getting error. I tried to follow the solution from this thread http://answers.opencv.org/question/18252/opencv-assertion-failed-for-perspective-transform/
_players[i].getCoordinates() is of type Point
_homography_matrix is a 3 x 3 Mat
Mat temp_Mat = Mat::zeros(2, 1, CV_32FC2);
for (int i = 0; i < _players.size(); i++)
{
cout << Mat(_players[i].get_Coordinates()) << endl;
perspectiveTransform(Mat(_players[i].get_Coordinates()), temp_Mat, _homography_matrix);
}
Also, how do I convert temp_Mat into type Point ?
OpenCV Error: Assertion failed (scn + 1 == m.cols) in cv::perspectiveTransform
Basically you just need to correct from
Mat(_players[i].get_Coordinates()) ...
to
Mat2f(_players[i].get_Coordinates()) ...
In the first case you are creating a 2x1, 1 channel float matrix, in the second case (correct) you create a 1x1, 2 channel float matrix.
You also don't need to initialize temp_Mat.
You can also use template Mat_ to better control the types of your Mats. E.g. creating a Mat of type CV_32FC2 is equivalent to create a Mat2f.
This sample code will show you also how to convert back and forth between Mat and Point:
#include <opencv2\opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
// Some random points
vector<Point2f> pts = {Point2f(1,2), Point2f(5,10)};
// Some random transform matrix
Mat1f m(3,3, float(0.1));
for (int i = 0; i < pts.size(); ++i)
{
cout << "Point: " << pts[i] << endl;
Mat2f dst;
perspectiveTransform(Mat2f(pts[i]), dst, m);
cout << "Dst mat: " << dst << endl;
Point2f p(dst(0));
cout << "Dst point: " << p << endl;
}
return 0;
}

Eigen: Concatenating matrices and vectors

Using the Eigen C++ library, I have a Matrix3f A, a Vector4f b, and a Vector4f c. I want to create a Matrix4f M out of these. I want the top 3-by-3 corner of M to be A, I want to final column of M to be b, and I want the bottom row of M to be c.
I know how to do this by simply creating a Matrix4f and assigning each element individually. But is there a more elegant solution that Eigen supports?
Does this count as elegant enough?
#include <Eigen/Sparse>
#include <iostream>
using namespace Eigen;
using std::cout;
using std::endl;
int main(int argc, char *argv[])
{
Matrix4f m = Matrix4f::Random();
Matrix3f A = Matrix3f::Constant(0.1);
Vector4f b = Vector4f::Constant(0.2), c = Vector4f::Constant(0.3);
cout << m << endl << endl;
cout << A << endl << endl;
cout << b << endl << endl;
cout << c << endl << endl;
m.block(0, 0, 3, 3) = A;
m.col(3) = b;
m.row(3) = c;
cout << m << endl << endl;
return 0;
}
Note that your question is kinda ambiguous, as the (3,3) position will be determined by the order of assignment between b and c.

Resources