C++ pow behaviour with negative vector size calculations - c++

After calling pow function with the argument as in the code bellow
it produces some high number as if it was accessing some invalid memory location.
I have no idea why this happens and any help would be greatly appreciated.
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
int main() {
vector<vector<int>> G = {
{1, 2, 3},
{0, 4}
};
cout << pow(G[1].size() - G[0].size(), 2) << endl;
return 0;
}
This prints 1.84467e+019.

The type of .size() is unsigned and you can not simply subtract them when the left operand is less than the right one.
Try this:
cout << pow((long) G[1].size() - (long)G[0].size(), 2) << endl;
~~~~~~ ~~~~~~
However, this solution is based on the assumption that casting the result of .size() fits into a signed long.
If you want a more defensive code, try this one:
size_t size_diff(size_t s0, size_t s1)
{
return s0 < s1? (s1 - s0) : (s0 - s1);
}
int main() {
// ...
cout << pow(size_diff(G[1].size(), G[0].size()), 2) << endl;
}

In addition to the accepted answer, I'd like to note that in C++20 we'll have std::ssize() free function that returns size as a signed type value. Then
std::pow(std::ssize(G[1]) - std::ssize(G[0]), 2)
will produce the correct result without explicit type casts.

Since pow takes a floating point value as its first argument, I'd suggest letting the compiler decide the right promotion by adding the difference to 0.0 (or 0.0L):
#include <iostream>
#include <cstdint>
#include <cmath>
using namespace std;
int main()
{
std::string name;
/// 52 of 64 bits used
uint64_t n1 = 0x000ffffffffffffd;
uint64_t n2 = 0x000fffffffffffff;
cout << "plain: " << n1 - n2 << endl;
cout << "float: " << (float)n1 - (float)n2 << endl;
cout << "double: " << (double)n1 - (double)n2 << endl;
cout << "long double: " << (long double)n1 - (long double)n2 << endl;
cout << "0.0+: " << 0.0 + n1 - n2 << endl;
cout << "0.0L+: " << 0.0L + n1 - n2 << endl;
cout << "pow(plain, 2): " << pow(n1-n2, 2) << endl;
cout << "pow(0.0+diff, 2): " << pow(0.0+n1-n2, 2) << endl;
cout << "pow(0.0L+diff, 2): " << pow(0.0L+n1-n2, 2) << endl;
}
The output
plain: 18446744073709551614
float: 0
double: -2
long double: -2
0.0+: -2
0.0L+: -2
pow(plain, 2): 3.40282e+38
pow(0.0+diff, 2): 4
pow(0.0L+diff, 2): 4
shows that plain subtraction goes wrong. Even casting to float doesn't suffice because float provides only a 23-bit mantissa.
The decision whether to use 0.0 or 0.0L for differences of size_t values returned by real std::vector::size() calls is theoretical for processes with address spaces below 4.5 Petabytes.
So I think the following will do:
cout << pow(0.0 + G[1].size() - G[0].size(), 2) << endl;

Related

How to take input and verify the result up to 4 decimal places?

My question was:
Write a program that reads three non-zero double values and determines and prints whether they are sides of a right triangle. The program should verify the results up to 4 decimal places.
[Hint: Use Pythagoras' theorem to determine whether the three sides form right triangle.]
The sample output is:
Enter length of three sides: 3 4 5
The sides represents right triangle.
Enter length of three sides: 4 5 6.403
The sides don’t represents right triangle.
Enter length of three sides: 4 5 6.4031
The sides represents right triangle.
I used this approach but can't understand how to verify up to 4 decimal places. Please help with this or at least give a hint.
My Code:
#include <iostream>
using namespace std;
int main() {
double s1, s2, s3;
cout<<"Enter length of three sides: ";
cin>>s1>>s2>>s3;
s1 *= s1;
s2 *= s2;
s3 *= s3;
if ((s1 == s2 + s3) || (s2 == s1 + s3) || (s3 == s1 + s2)) {
cout<<"The sides represents right triangle."<<endl;
}
else {
cout<<"The sides don't represents right triangle."<<endl;
}
}
Someone told me use for setprecision, but how?
It is all about rounding and also about the precision of double numbers. Comparison for equality is basically not possible.
As you have read in the comments and as for example shown here, there are ways to somehow compare doubles.
And here your 4th decimal place will help.
Comparison can basically done with the following formula:
bool equal(double a, double b) {
return fabs(a - b) < EPSILON;
}
And here we can set the epsilon to 0.001, which gives you the desired result.
Do not forget to find the hypotenuse! This is the longest side.
Please see the following example:
#include <iostream>
#include <iomanip>
#include <limits>
#include <array>
#include <algorithm>
int main() {
// Tell user what to do
std::cout << "\nEnter length of three sides: ";
// Get length of the 3 sides of the triangle
std::array<double, 3> side{};
if ((std::cin >> side[0] >> side[1] >> side[2]) and (side[0] > 0) and (side[1] > 0) and (side[2] > 0)) {
// Get Hypotenuse
std::sort(side.begin(), side.end());
// You may enable debug output by setting to 1
#if 0
// Debug output
std::cout << std::setprecision(30) <<"\n\nDebug output\na: " << side[0] << '\n';
std::cout << "b: " << side[1] << '\n';
std::cout << "c: " << side[2] << '\n';
std::cout << "a*a: " << side[0] * side[0] << '\n';
std::cout << "b*b: " << side[1] * side[1] << '\n';
std::cout << "c*c: " << side[2] * side[2] << '\n';
std::cout << "a*a + b*b: " << side[0] * side[0] + side[1] * side[1] << '\n';
std::cout << "abs((a*a+b*b)-(c*c)): " << std::fabs(((side[0] * side[0]) + (side[1] * side[1])) - (side[2] * side[2])) << "\n\n\n";
#endif
// Phythagoras and comparison
if (std::fabs(((side[0] * side[0]) + (side[1] * side[1])) - (side[2] * side[2])) < 0.001)
std::cout << "The sides represents right triangle.\n";
else
std::cout << "The sides don’t represents right triangle.\n";
}
else std::cerr << "\n\n*** Error: Invalid input\n\n";
}

Difference in evaluation of expression when using long long int vs double in c++ [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed last year.
I'll refer to the below code to explain my question.
typedef long long int ll;
void func(){
ll lli_a = 603828039791327040;
ll lli_b = 121645100408832000;
double d_b = (double)lli_b;
cout << "a " << lli_b - d_b << endl; \\0
cout << "b " << (lli_a - 4*lli_b) - (lli_a - 4*d_b) << endl; \\64
cout << "c " << (lli_a - 4*lli_b) - (lli_a - (ll)4*d_b) << endl; \\64
cout << "d " << (lli_a - 4*lli_b) - (lli_a - 4*(ll)d_b) << endl; \\0
cout << "e " << 4*(ll)d_b - 4*d_b << endl; \\0
cout << "f " << 4*(ll)d_b - (ll)4*d_b << endl; \\0
}
I'm unable to understand why statements b and c have evaluated to 64, while d has evaluated to 0, which happens to be the correct answer.
Both e and f evaluate to 0, so the difference is coming because of subtraction from lli_a I assume. I don't think there is any overflow issue as individual values for each term are coming correctly.
double is a floating point type. Floating point types have limited precision. They cannot represent all numbers - not even all rational numbers. Simply (on your system) 603828039791327040 is a number that cannot be represented by the double datatype. The closest value that is representable happens to be 64 away from the precise value.
You can (likely) get the expected result by using long double which (typically) can represent all values of long long - or you could avoid using floating point in the first place.
Some code to walk you through it, bottom line don't mix doubles with ints implicitly
#include <cassert>
#include <iostream>
#include <type_traits>
// typedef long long int ll; NO , use using and never use aliasing to safe a bit of typing. Aliases are there to introduce meaning not shortcuts
//using namespace std; // also NO
int main()
{
long long int lli_a = 603828039791327040;
long long int lli_b = 121645100408832000;
//double d_b = (double)lli_b; // No this is C++ don't use 'C' style casts
double d_b = static_cast<double>(lli_b);
assert(static_cast<long long int>(d_b) == lli_b); // you are in luck the double can represent your value exectly, NOT guaranteed
std::cout << "a " << lli_b - d_b << "\n"; // endl; \\0 don't use endl unless you have a good reason to flush
long long int lli_b4 = 4 * lli_b;
// use auto to show you this expression evaluates to a double!
auto lli_d_b4 = (lli_a - static_cast<long long int>(4) * d_b); // d_b is double!!! what do you want to do here? Use it as a long long int then cast it first
static_assert(std::is_same_v<double, decltype(lli_d_b4)>);
auto result_c = lli_b4 - lli_d_b4;
// result c is still a double!
static_assert(std::is_same_v<double, decltype(result_c)>);
std::cout << "c " << result_c << "\n";
// long story short don't mix types implicitly and use "C++" style cast explicitly to get the results you want
/*
cout << "b " << (lli_a - 4 * lli_b) - (lli_a - 4 * d_b) << endl; \\64
cout << "c " << (lli_a - 4 * lli_b) - (lli_a - (ll)4 * d_b) << endl; \\64
cout << "d " << (lli_a - 4 * lli_b) - (lli_a - 4 * (ll)d_b) << endl; \\0
cout << "e " << 4 * (ll)d_b - 4 * d_b << endl; \\0
cout << "f " << 4 * (ll)d_b - (ll)4 * d_b << endl; \\0
*/
return 0;
}

Program that finds the number you are thinking doesn't work properly, what is wrong?

Im having trouble with this recursion code. Basically I want the computer to "guess" in as little steps as possible the number that I am thinking of. However, everything works except the final output. The bounds are fine, and it narrows down the guess until it asks me if the number im thinking of is say 16, if I input "=" it should output 16 instead it always outputs 50. Could anyone help me locate the error?
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
unsigned int search (unsigned int boundInf, unsigned int boundSup);
int main ()
{
int b;
b = search (1, 100);
cout << "Your number must be : " << b << endl;
}
unsigned int search (unsigned int boundInf, unsigned int boundSup)
{
string magnitude;
int b;
b = (boundSup + boundInf) / 2;
cout << "Is your number <, > or = to " << b << "? ";
cin >> magnitude;
if (magnitude == "<") {
cout << "Between " << boundInf << " and " << b << endl;
search (boundInf, b);
}
else if (magnitude == ">") {
cout << "Between " << b << " and " << boundSup << endl;
search (b, boundSup);
}
return b;
}
You forgot to change the value of b when going deeper into the recursive function, this can be easily fixed by changing the search function like so:
unsigned int search(unsigned int boundInf, unsigned int boundSup)
{
string magnitude;
int b;
b = (boundSup + boundInf) / 2;
cout << "Is your number <, > or = to " << b << "? ";
cin >> magnitude;
if (magnitude == "<")
{
cout << "Between " << boundInf << " and " << b << endl;
b = search(boundInf, b);
}
else if (magnitude == ">")
{
cout << "Between " << b << " and " << boundSup << endl;
b = search(b, boundSup);
}
return b;
}

Issue with fmod with doubles

It would seem fmod(x,1) where x is a double gives the wrong result, as output by the line:
std::cout << fmod(min, 1) << "|" << fmod(max, 1) << std::endl;
I forgot the name for what you call this, but this is the smallest amount of code necessary to illustrate my problem:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <math.h>
const int deviation = 3;
void weightedRandomNumber(double min, double max);
int main() {
srand(time(nullptr));
std::cout.precision(16);
std::cout << 123.1 << "|" << 2789.3234 << std::endl;
weightedRandomNumber(123.1, 2789.3234);
system("pause");
return 0;
}
void weightedRandomNumber(double min, double max) {//inclusive
int multiplier = 1;
std::cout << min << "|" << max << std::endl;
while (fmod(min, 1) > 0 || fmod(max, 1) > 0) {
std::cout << min << "|" << max << std::endl;
std::cout << fmod(min, 1) << "|" << fmod(max, 1) << std::endl;
min *= 10;
max *= 10;
multiplier++;
}
std::cout << min << "|" << max << std::endl;
std::cout << multiplier << std::endl;
}
The outputs I get when I run the code are as such:
123.1|2789.3234
123.1|2789.3234
123.1|2789.3234
0.09999999999999432|0.3234000000002197
1231|27893.234
0|0.2340000000040163
12310|278932.34
0|0.3400000000256114
123100|2789323.4
0|0.400000000372529
1231000|27893234
0|3.725290298461914e-09
12310000|278932340.0000001
0|5.960464477539063e-08
123100000|2789323400
0|4.76837158203125e-07
1231000000|27893234000
0|3.814697265625e-06
12310000000|278932340000.0001
0|6.103515625e-05
123100000000|2789323400000
0|0.00048828125
1231000000000|27893234000000
0|0.00390625
12310000000000|278932340000000
0|0.03125
123100000000000|2789323400000001
0|0.5
1231000000000000|2.7893234e+16
14
Other than this I don't quite know what to say, if I have missed anything necessary please comment so I can amend my question.
The issue is not with fmod, which is giving the highest precision results it can. The issue is with cout precision not behaving like you expect, combined with "rounding" because a double cannot store 0.1 accurately enough to represent what cout considers a precision of 16.
This code demonstrates the issue. The rounding actually occurs when you assign 123.1 to a double, but because of the 3 digits to the left is not visible until it becomes a smaller number.
int main() {
std::cout.precision(16);
std::cout << (123.1L - 123L);
}
output:
0.09999999999999432
Actually....this illustrates the problem even more succinctly:
int main() {
std::cout.precision(20);
std::cout << 123.1;
}
123.09999999999999432
Further reading from the comments on your question:
Is floating point math broken?
Also, for the vast majority of scenarios, a double is more than fine. For accurate, recursive math, you'd want to consider a heavy-duty math library, or even a math-specialized language.
Further further reading:
http://www.boost.org/doc/libs/1_62_0/libs/math/doc/html/math_toolkit/high_precision/why_high_precision.html

fmod telling me fractional part of 1 is 1

I'm trying to check if a double variable p is approximately equal to an integer. At some point in my code I have
double ip;
cout << setprecision(15) << abs(p) << " " << modf(abs(p), &ip) << endl;
And for a given run I get the printout
1 1
This seems to say that the fractional part of 1 is 1, am I missing something here or could there be some roundoff problem etc?
Note: I'm not including the whole code since the origin of p is complicated and I'm just asking if this is a familiar issue
could there be some roundoff problem etc?
There certainly could. If the value is very slightly less than 1, then both its value and its fractional part could be rounded to 1 when displayed.
the origin of p is complicated
Then it's very likely not to be an exact round number.
You are testing a nearly-1-value, so precision of 15 is not enough to describe it unambiguously.
This code shows your problem clearly:
#include <iostream>
#include <iomanip>
#include <cmath>
#include <limits>
using namespace std;
int main() {
double ip, d = nextafter(1., .0); // Get a double just smaller than 1
const auto mp = std::numeric_limits<double>::max_digits10;
cout << 15 << ": " << setprecision(15)
<< abs(d) << " " << modf(abs(d), &ip) << '\n';
cout << mp << ": " << setprecision(mp)
<< abs(d) << " " << modf(abs(d), &ip) << '\n';
}
On coliru: http://coliru.stacked-crooked.com/a/e00ded79c1727299
15: 1 1
17: 0.99999999999999989 0.99999999999999989