Precision of double in this code is only 6 digits - c++

double a_0_d = 2 * sqrt(3);
double b_0_d = 3;
double ak_d = 0, bk_d = 0;
while ((a_0_d-b_0_d) != 0) {
ak_d = a_0_d;
bk_d = b_0_d;
a_0_d = (2 * ak_d * bk_d) / (ak_d + bk_d);
b_0_d = sqrt(a_0_d * bk_d);
//cout << a_0_d << " " << b_0_d << endl;
}
pi_double = a_0_d;
cout << "The pi_double value at double precision is = " << pi_double << endl;
Output: 3.14159
I thought the precision of double is 15 digits, is it possible that the output is converted to float data type?

You should use std::setprecision:
#include <iomanip>
cout << "The pi_double value at double precision is = " << std::setprecision(15) << pi_double << endl;
Live on godbolt

Related

I would appreciate help converting ints/floats to strings in c++

#include <iostream>
using namespace std;
int fiveYears;
fiveYears = 5 * 1.5;
int sevenYears;
sevenYears = 7 * 1.5;
int tenYears;
tenYears = 10 * 1.5;
int main()
{
cout << "In years the ocean's level will be higher by " << fiveYears << "millimeters\n";
cout << "In years the ocean's level will be higher by " << sevenYears << "millimeters\n";
cout << "In years the ocean's level will be higher by " << tenYears << "millimeters\n";
return 0;
}
So this is what I have so far. I have only started c++ about a week ago and I am still unsure about how to convert floats and integers into strings. My output should prints the statements with the results of the strings.
You can either use this
#include <iostream>
using namespace std;
int fiveYears;
int sevenYears;
int tenYears;
int main()
{
fiveYears = 5 * 1.5;
sevenYears = 7 * 1.5;
tenYears = 10 * 1.5;
cout << "In years the ocean's level will be higher by " << fiveYears << " millimeters\n";
cout << "In years the ocean's level will be higher by " << sevenYears << " millimeters\n";
cout << "In years the ocean's level will be higher by " << tenYears << " millimeters\n";
return 0;
}
or this
#include <iostream>
using namespace std;
int fiveYears = 5 * 1.5;
int sevenYears = 7 * 1.5;
int tenYears = 10 * 1.5;
int main()
{
cout << "In years the ocean's level will be higher by " << fiveYears << " millimeters\n";
cout << "In years the ocean's level will be higher by " << sevenYears << " millimeters\n";
cout << "In years the ocean's level will be higher by " << tenYears << " millimeters\n";
return 0;
}
to resolve this issue if you really want to use global variables.
You can use std::to_string
Converts a numeric value to std::string.
Example
#include <iostream>
int main()
{
int v1 = 61;
long v2 = 62L;
long long v3 = 63LL;
unsigned int v4 = 64;
unsigned long v5 = 65UL;
unsigned long long v6 = 66ULL;
float v7 = 67.0f;
double v8 = 68.0;
long double v9 = 69.0L;
std::string v1Str = std::to_string(v1);
std::string v2Str = std::to_string(v2);
std::string v3Str = std::to_string(v3);
std::string v4Str = std::to_string(v4);
std::string v5Str = std::to_string(v5);
std::string v6Str = std::to_string(v6);
std::string v7Str = std::to_string(v7);
std::string v8Str = std::to_string(v8);
std::string v9Str = std::to_string(v9);
std::cout << v1Str << std::endl;
std::cout << v2Str << std::endl;
std::cout << v3Str << std::endl;
std::cout << v4Str << std::endl;
std::cout << v5Str << std::endl;
std::cout << v6Str << std::endl;
std::cout << v7Str << std::endl;
std::cout << v8Str << std::endl;
std::cout << v9Str << std::endl;
int fiveYears = 5;
int sevenYears = 7;
int tenYears = 10;
float ratio = 1.5;
std::cout << u8"In " + std::to_string(fiveYears) + u8" years the ocean\'s level will be higher by " + std::to_string(fiveYears * ratio) + u8" millimeters" << std::endl;
std::cout << u8"In " + std::to_string(sevenYears) + u8" years the ocean\'s level will be higher by " + std::to_string(sevenYears * ratio) + u8" millimeters" << std::endl;
std::cout << u8"In " + std::to_string(tenYears) + u8" years the ocean\'s level will be higher by " + std::to_string(tenYears * ratio) + u8" millimeters" << std::endl;
}
Output
61
62
63
64
65
66
67.000000
68.000000
69.000000
In 5 years the ocean's level will be higher by 7.5 millimeters
In 7 years the ocean's level will be higher by 10.5 millimeters
In 10 years the ocean's level will be higher by 15 millimeters
Check/run this example in https://repl.it/#JomaCorpFX/IntFloatsToString#main.cpp

Creating a C++ program to solve an equation of motion using Euler's method

I am trying to compute the time history of the velocity described by the equation:
dV/dt = g − (C_d/m) * V^2. g = 9.81, m = 1.0, and C_d = 1.5.
To do this I need to create a program in c++ that uses the Euler explicit method to numerically solve the equation. I am trying to find the velocity from t = 0 to t = 1 seconds with three different step sizes of delta_t = 0.05, 0.1, and 0.2 seconds. And then you are supposed to show your percent error to the analytical solution given as: V(t) = sqrt((m*g)/C_d) * tanh(sqrt((g*C_d)/m) * t).
My problem is I am not sure how to iterate through Euler's method multiple times with different time intervals. So far I have solved the analytical equation, but am unsure where to go from here. If anyone could help point me in the right direction it would be greatly appreciated.
#include <iomanip>
#include <cmath>
#include <math.h>
using namespace std;
int main() {
double m = 1.0; // units in [kg]
double g = 9.81; // units in [m/s^2]
double C_d = 1.5; // units in [kg/m]
double t; // units in [s]
double v; // units in [m/s]
cout << "The velocity will be examined from the time t = 0 to t = 1 seconds." << endl;
cout << "Please select either 0.05, 0.1, or 0.2 to be the time interval:" << endl;
cin >> t;
cout << "You have chosen the time interval of: " << t << " seconds." << endl;
v = sqrt((m * g) / C_d) * tanh(sqrt((g * C_d) / m) * t);
cout << "The velecity at a time of "<< t << " seconds is equal to: " << v << " m/s." << endl;
return 0;
} ```
If you want to iterate over t with increments of A, calculating the result of the formula with each t, you would write a for loop.
#include <iostream>
int main()
{
double m = 1.0; // units in [kg]
double g = 9.81; // units in [m/s^2]
double C_d = 1.5; // units in [kg/m]
std::cout << "The velocity will be examined from the time t = 0 to t = 1 seconds." << std::endl;
std::cout << "Please select the time interval:" << std::endl;
std::cout << "1: 0.05" << std::endl;
std::cout << "2: 0.1" << std::endl;
std::cout << "3: 0.2" << std::endl;
double A = 0; // increment in for loop
int x;
std::cin >> x;
switch (x) { // check what the input is equal to
case 1: A = 0.05; break;
case 2: A = 0.1; break;
case 3: A = 0.2; break;
default: std::cout << "Unknown option!" << std::endl; return 1;
}
std::cout << "You have chosen the time interval of: " << A << " seconds." << std::endl;
std::cout << "Results of V(t):" << std::endl;
// this initializes a variable t as 0,
//and while t is lower than or equal to 1,
//it will increment it by a and execute the logic within the scope of the loop.
for (double t = 0; t < (1 + A); t += A) {
std::cout << "at t = " << t << ": " << sqrt((m*g) / C_d) * tanh(sqrt((g*C_d) / m) * t) << std::endl;
}
return 0;
}
Refer to https://beginnersbook.com/2017/08/cpp-for-loop/ for more information. Note: I've also introduced a switch statement into the code to prevent unknown values from being input. https://beginnersbook.com/2017/08/cpp-switch-case/

How can I justify my cursor to line up with my output colums in a terminal program?

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
const double PI = 3.14159;
double rad = 0;
double area = 0;
double vol = 0;
int areaPi = 0;
int volPi = 0;
cout << setprecision(5) << fixed;
cout << setw(38) << left << "Enter radius for the sphere: " << right);
cin >> rad;
area = (4 * PI * (rad * rad));
vol = ((4.0/3.0) * PI * (rad * rad * rad));
areaPi = (4 * (rad *rad));
volPi = (4 * (rad * rad * rad));
cout << right << "Surface area of the sphere: " << setw(12) << area << " (" << areaPi << "\u03C0)";
cout << "\n";
cout << "The volume of the sphere: " << setw(14) << vol << " (" << volPi << "π/3)";
cout << "\n";
return 0;
}
Hi guys. So the problem I'm having is that when you enter a value for the radius (rad) variable the cursor wants to work its way from the left to the right when the user types resulting in double digit numbers being longer than the output columns.
It looks like this when the program runs and you enter anything longer than one digit:
//Enter radius for the sphere: 17
//Surface area of the sphere: 3631.67804 (1156π)
//The volume of the sphere: 20579.50889 (19652π/3)
I would like the 7 to line up with the column below it. I tried setting the width to one less than I had before & single digits end up one space too far to the left like so:
//Enter radius for the sphere: 4
//Surface area of the sphere: 201.06176 (64π)
//The volume of the sphere: 268.08235 (256π/3)
I would store the output into a set of strings. Then you could check and manipulate the data as needed. Alternatively you could calculate the offset of spaces you'd need before printing
// convert to string for digit count
std::string output_1 = std::to_string(x);
std::string output_2 = std::to_string(y);
int o_1_2_dist = output_1.size() - output_2.size(); // difference in digits
std::string padding_1, padding_2;
if (o_1_2_dist < 0)
padding_1 = std::string(abs(o_1_2_dist), ' ');
else
padding_2 = std::string(o_1_2_dist, ' ');
std::cout << padding_1 << output_1 << '\n' << padding_2 << output_2;
you'd want to adjust on of the output strings so it doesn't count the extra bits of the number you don't care about. Maybe do output_1 = std::to_string(floor(x)); or something like that so you don't count the digits after the decimal
This can be solved by calculating the length of the input. I used c++11's to_string to convert the resulting values to strings and find out their lengths. I haven't tried how portable that is. It seems to work under linux with gcc 6.1.1., but for some reason it did not work with the input, so I changed that part as well so that the users enters a std::string which gets converted to a double afterwards.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
const double PI = 3.14159;
double rad = 0;
double area = 0;
double vol = 0;
int areaPi = 0;
int volPi = 0;
int width_col1 = 40;
//cout.fill('.');
cout << setprecision(5) << fixed;
cout << left << setw(width_col1) << "Enter radius for the sphere: " << right;
std::string input;
cin >> input;
rad = stod(input);
area = (4 * PI * (rad * rad));
vol = ((4.0/3.0) * PI * (rad * rad * rad));
areaPi = (4 * (rad *rad));
volPi = (4 * (rad * rad * rad));
int indent = width_col1 + input.length() + 1;
cout << left << setw(indent - to_string(area).length()) << "Surface area of the sphere: " << area << " (" << areaPi << "\u03C0)" << std::endl;
cout << left << setw(indent - to_string(vol).length()) << "The volume of the sphere: " << vol << " (" << volPi << "π/3)" << std::endl;
return 0;
}
This solution resembles what C programmers would have done with printf.
I would love to learn why this did not work with the input.

Significant figures in C++

I've written a program that calculates values in a series and all of the values are particularly lengthy doubles. I want to print these values each displaying 15 significant figures. Here's some code that illustrates the issue I'm having:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
cout << setprecision(15) << fixed << x << "\t" << y << "\n";
return 0;
}
With just setprecision trailing zeros are not shown so I added fixed as I have seen in other answers on this site. However, now I just seem to have 15 decimal places and for values that aren't 0.something this is not what I want. You can see this from the output of the above:
0.123456789012346 1.123456789012346
The first number has 15 sig figs but the second has 16. What can I do to resolve this?
EDIT: I have been specifically asked to use setprecision, so I am unable to try cout.precision.
You can simply use scientific (note the 14 instead of 15):
std::cout << std::scientific << std::setprecision(14) << -0.123456789012345678 << std::endl;
std::cout << std::scientific << std::setprecision(14) << -1.234567890123456789 << std::endl;
-1.23456789012346e-01
-1.23456789012346e+00
or you can use a function:
#include <iostream>
#include <vector>
#include <iomanip>
#include <string>
#include <sstream>
enum vis_opt { scientific, decimal, decimal_relaxed };
std::string figures(double x, int nfig, vis_opt vo=decimal) {
std::stringstream str;
str << std::setprecision(nfig-1) << std::scientific << x;
std::string s = str.str();
if ( vo == scientific )
return s;
else {
std::stringstream out;
std::size_t pos;
int ileft = std::stoi(s,&pos);
std::string dec = s.substr(pos + 1, nfig - 1);
int e = std::stoi(s.substr(pos + nfig + 1));
if ( e < 0 ) {
std::string zeroes(-1-e,'0');
if ( ileft < 0 )
out << "-0." << zeroes << -ileft << dec;
else
out << "0." << zeroes << ileft << dec;
} else if ( e == 0) {
out << ileft << '.' << dec;
} else if ( e < ( nfig - 1) ) {
out << ileft << dec.substr(0,e) << '.' << dec.substr(e);
} else if ( e == ( nfig - 1) ) {
out << ileft << dec;
} else {
if ( vo == decimal_relaxed) {
out << s;
} else {
out << ileft << dec << std::string(e - nfig + 1,'0');
}
}
return out.str();
}
}
int main() {
std::vector<double> test_cases = {
-123456789012345,
-12.34567890123456789,
-0.1234567890123456789,
-0.0001234,
0,
0.0001234,
0.1234567890123456789,
12.34567890123456789,
1.234567890123456789,
12345678901234,
123456789012345,
1234567890123456789.0,
};
for ( auto i : test_cases) {
std::cout << std::setw(22) << std::right << figures(i,15,scientific);
std::cout << std::setw(22) << std::right << figures(i,15) << std::endl;
}
return 0;
}
My output is:
-1.23456789012345e+14 -123456789012345
-1.23456789012346e+01 -12.3456789012346
-1.23456789012346e-01 -0.123456789012346
-1.23400000000000e-04 -0.000123400000000000
0.00000000000000e+00 0.00000000000000
1.23400000000000e-04 0.000123400000000000
1.23456789012346e-01 0.123456789012346
1.23456789012346e+01 12.3456789012346
1.23456789012346e+00 1.23456789012346
1.23456789012340e+13 12345678901234.0
1.23456789012345e+14 123456789012345
1.23456789012346e+18 1234567890123460000
I've found some success in just computing the integer significant figures, and then setting the floating significant figures to be X - <integer sig figs>:
Edit
To address Bob's comments, I'll account for more edge cases. I've refactored the code somewhat to adjust the field precision based on leading and trailing zeros. There would still be an edge case I believe for very small values (like std::numeric_limits<double>::epsilon:
int AdjustPrecision(int desiredPrecision, double _in)
{
// case of all zeros
if (_in == 0.0)
return desiredPrecision;
// handle leading zeros before decimal place
size_t truncated = static_cast<size_t>(_in);
while(truncated != 0)
{
truncated /= 10;
--desiredPrecision;
}
// handle trailing zeros after decimal place
_in *= 10;
while(static_cast<size_t>(_in) == 0)
{
_in *= 10;
++desiredPrecision;
}
return desiredPrecision;
}
With more tests:
double a = 0.000123456789012345;
double b = 123456789012345;
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
double z = 11.12345678901234567890;
std::cout.setf( std::ios::fixed, std:: ios::floatfield);
std::cout << "a: " << std::setprecision(AdjustPrecision(15, a)) << a << std::endl;
std::cout << "b: " << std::setprecision(AdjustPrecision(15, b)) << b << std::endl;
std::cout << "x " << std::setprecision(AdjustPrecision(15, x)) << x << std::endl;
std::cout << "y " << std::setprecision(AdjustPrecision(15, y)) << y << std::endl;
std::cout << "z: " << std::setprecision(AdjustPrecision(15, z)) << z << std::endl;
Output:
a: 0.000123456789012345
b: 123456789012345
x 0.123456789012346
y 1.12345678901235
z: 11.1234567890123
Live Demo
int GetIntegerSigFigs(double _in)
{
int toReturn = 0;
int truncated = static_cast<int>(_in);
while(truncated != 0)
{
truncated /= 10;
++toReturn;
}
return toReturn;
}
(I'm sure there are some edge cases I'm missing)
And then using it:
double x = 0.12345678901234567890;
double y = 1.12345678901234567890;
std::cout << td::setprecision(15-GetIntegerSigFigs(x)) << x
<< "\t" << std::setprecision(15-GetIntegerSigFigs(y)) << y << "\n";
Prints:
0.123456789012346 1.12345678901235
Live Demo

Introductory C++ program

I have tried tirelessly to get this right, but nothing seems to work. A lot of what I do brings me to an error 'Control may reach end of non-void function'.
Basically, we created a program to output gas usage statistics. What I am stuck on is:
"Gas will rise in price from the defined initial value to the defined final value over the course of 4 years, then remain fixed at that higher value for the next 4 years."
I feel like there should be a loop or function for this, but every time I make NUM_YEARS an int rather than a const, no matter what the program tells me 'Control may reach end of non-void function.'
Below is the program:
#include <cstdlib>
#include <iostream>
using namespace std;
const int MILES_PER_YEAR = 21000;
const double CITY_PERCENT = 45.0;
const double HIGHWAY_PERCENT = 55.0;
const double CITY_MPG = 51.0;
const double HIGHWAY_MPG = 45.0;
const double USABLE_GAS = 9.0;
const double INITIAL_PRICE = 3.359;
const double FINAL_PRICE = 6.00;
const int NUM_YEARS = 8; //This will be the total number of years
double gasPrice(int day);
int main(int argc, char * argv[]) {
cout << "Driving the Toyota Prius" << endl;
double daily_miles = MILES_PER_YEAR / 365.0;
double daily_city_miles = daily_miles * CITY_PERCENT/100.0;
double daily_highway_miles = daily_miles*HIGHWAY_PERCENT/100.0;
double daily_gas_consumed = daily_highway_miles / HIGHWAY_MPG +
daily_city_miles / CITY_MPG;
double gas_in_tank = USABLE_GAS;
double price;
double amount_purchased;
double gallons_purchased;
double total_gas_purchases = 0;
for(int day = 0;day < 365*8; day++) { //If the day is less than the total number of days in 8 years, add one day
cout << "Driving summary for day " << day << endl;
cout << " highway miles: " << daily_highway_miles << endl;
cout << " city miles : " << daily_city_miles << endl;
cout << " gas consumed : " << daily_gas_consumed << endl;
gas_in_tank = gas_in_tank - daily_gas_consumed;
cout << " gas in tank : " << gas_in_tank << endl;
if (gas_in_tank < 0.0) {
cout << " BUY GAS" << endl;
gallons_purchased = USABLE_GAS - gas_in_tank;
price = gasPrice(day);
cout << " price today is : " << price << endl;
cout << " Gallons purchased: " << gallons_purchased << endl;
cout << " fillup cost : " << gallons_purchased * price << endl;
total_gas_purchases = total_gas_purchases + gallons_purchased * price;
cout << " total gas cost : " << total_gas_purchases << endl;
gas_in_tank = USABLE_GAS;
}
}
system("PAUSE");
return EXIT_SUCCESS;
}
double gasPrice(int day, int YEAR_NUM) {
if (int day=365) { //call YEAR_NUM, for day=365, increase YEAR_NUM by 1
YEAR_NUM++;
day = 0;
}
if (YEAR_NUM >= 4) {
double currentPrice = FINAL_PRICE;
currentPrice;
}
if (YEAR_NUM < 4) { //conditional price for the first four years
double dailyIncrease = (FINAL_PRICE - INITIAL_PRICE) / (NUM_YEARS * 365);
double currentPrice = (INITIAL_PRICE + day * dailyIncrease);
return currentPrice;
}
}
You need to return something in gasPrice that is outside of the for loop. The compiler is saying there is a chance that neither of the while conditions will be met, in which case there is no value to return.
On another note, the while loops do not make a lot of sense the way they are written. Just make them if statements.
I think if you move "return currentPrice;" out of those two while loops, it will fix the problem.
Function gasPrice has no return statement outside the for loop. As the function has a return type that is not void then if the return statement is absent the behaviour of the function will be undefined.