For determining how many terms are required for the first time getting pi that begins with 3.14159 I wrote the following program that calculates terms as (pi = 4 - 4/3 + 4/5 - 4/7 + ...).
My problem is that I reached 146063 terms as the result but when I checked, there are many pis that begin similarly before that.
//piEstimation.cpp
//estima mathematical pi and detrmin when
//to get a value beganing with 3.14159
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
int main(){
//initialize vars
double denominator{1.0};
double pi{0};
string piString;
double desiredPi;
int terms;
int firstDesiredTerm;
//format output floating point numbers to show 10 digits after
// decimal poin
cout << setprecision (10) <<fixed;
for (terms = 1; ; terms++){
if(0 == terms % 2){ //if term is even
pi -= 4/denominator;
}
else{ //if term is odd
pi += 4/denominator;
}
// draw table
cout << terms << "\t" << pi << endl;
//determin first time the pi begains with 3.14159
piString = to_string(pi).substr(0,7);
if(piString == "3.14159"){
firstDesiredTerm = terms;
desiredPi = pi;
break;
}
denominator += 2;
}//end for
cout << "The first time that pi value begans with 3.14159 "
<< "the number of terms are " << firstDesiredTerm << " and pi value is "<< desiredPi <<endl;
}//end main
A number x begins with 3.14159 if x >= 3.14159 && x < 3.1416. There is no need to use strings and compare characters. to_string has to use some kind of round operation. Without the string the algorithm finds the result after 136121 steps
#include <iostream>
#include <iomanip>
int main(){
//initialize vars
double denominator{1.0};
double pi{0};
double desiredPi;
int terms;
int firstDesiredTerm;
//format output floating point numbers to show 10 digits after
// decimal poin
std::cout << std::setprecision (20) << std::fixed;
for (terms = 1; ; terms++){
if(0 == terms % 2){ //if term is even
pi -= 4/denominator;
}
else{ //if term is odd
pi += 4/denominator;
}
// draw table
std::cout << terms << "\t" << pi << std::endl;
if(pi >= 3.14159 && pi < 3.1416){
firstDesiredTerm = terms;
desiredPi = pi;
break;
}
denominator += 2;
}//end for
std::cout << "The first time that pi value begans with 3.14159 "
<< "the number of terms are " << firstDesiredTerm
<< " and pi value is "<< desiredPi << std::endl;
}
Output:
The first time that pi value begans with 3.14159 the number of terms are 136121 and pi value is 3.14159999999478589672
Here you can see how to_string rounds the result:
#include <iostream>
#include <iomanip>
#include <string>
int main(){
std::cout << std::setprecision (20) << std::fixed;
std::cout << std::to_string(3.14159999999478589672) << '\n';
}
Output:
3.141600
You can read on cppreference
std::string to_string( double value ); Converts a floating point value to a string with the same content as what std::sprintf(buf, "%f", value) would produce for sufficiently large buf.
You can read on cppreference
f F Precision specifies the exact number of digits to appear after the decimal point character. The default precision is 6
That means that std::to_string rounds after 6 digits.
Related
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int(main){
std::vector<int> vObj;
float n = 0.59392;
int nCopy = n;
int temNum = 0;;
while (fmod(nCopy, 1) != 0) {
temNum = (nCopy * 10); cout << endl << nCopy << endl;
nCopy *= 10;
vObj.push_back(temNum);
cout << "\n\n Cycle\n\n";
cout << "Temp Num: " << temNum << "\n\nN: " << nCopy << endl;
}
return 0;
}
For example, I input 0.59392 but eventually when the code reaches the bottom, where it should be going
5939.2 and then go to
59392 and stop but for some reason
it keeps going.
yeah , so you have 3 major problems in your code , first of all : it's int main() not int(main) . second : the variable named **nCopy ** is not supposed to be a integer data type , third one : you have to know what the actual representation of the float number , but first this is my solution for your problem , it's not the best one , but it works for this case :
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;
int main() {
std::vector<int> vObj;
double n = 0.59392;
double nCopy = n;
int temNum = 0;;
while (fmod(nCopy, 1) != 0) {
temNum = (nCopy * 10); cout << endl << nCopy << endl;
nCopy *= 10;
vObj.push_back(temNum);
cout << "\n\n Cycle\n\n";
cout << "Temp Num: " << temNum << "\n\nN: " << nCopy << endl;
}
return 0;
}
so the explanation is as follow , the double data types gives higher precision than float , that's why I used double instead of float , but it will lack accuracy when the number becomes big .
second of : you have to how is float or double is represented , as the value 0.59392 is actually stored in the memory as value 0.593900024890899658203125 when using float according to IEEE 754 standard , so there are other types of decimals to solve this problem where the difference between them is as follow
Decimal representation gives lower accuracy but higher range with big numbers and high accuracy when talking about small numbers, most 2 used standards are binary integer decimal (BID) and densely packed decimal (DPD)
float and doubles gives higher accuracy than Decimal when talking about big numbers but lower range ,they follow IEEE 754 standard
Fixed-Point types have the lowest range but they are the most accurate one and they are the fastest ones
but unfortunately , C++ only supports float and double types of numbers , but I believe there is external libraries out there to define a decimal data type.
I'm sending the value 4 *cos( fmod( acos(2.0/4.0), 2*3.14159265) ) as double to this function but I get output as
2
1k1
What is wrong here?
void convert_d_to_f(double n)
{
cout<<n<<" ";
double mantissa;
double fractional_part;
fractional_part = modf(n,&mantissa);
double x = fractional_part;
cout<<mantissa<<"k"<<fractional_part<<'\n';
}
The problem is that cout truncates and rounds double while printing. You can print the desired number of decimal places usingiomanip library.
#include <iostream>
#include <cmath>
#include <iomanip>
void convert_d_to_f(double n)
{
cout<<std::fixed<<std::setprecision(20); //number of decimal places you need to print to
cout<<n<<" ";
double mantissa;
double fractional_part;
fractional_part = modf(n,&mantissa);
double x = fractional_part;
cout<<mantissa<<"k"<<fractional_part<<'\n';
}
int main() {
convert_d_to_f(4 *cos( fmod( acos(2.0/4.0), 2*3.14159265) ));
return 0;
}
For all practical intents and purposes, your number n evaluates to 2. If you want it to display as 1.9999999... etc. then follow Kapil's solution and set the floating point precision for std::cout to many decimal places. Keep in mind the difference between precision and accuracy if you are going to go that route.
That being said, your void convert_d_to_f(double n) function is replicating the functionality of std::frexp(double arg, int* exp) with a limitation where your results are going out of scope after you print them to the screen. If you desire to use your exponent and mantissa values after computing them, then you can do it like this.
#include <iostream>
#include <cmath>
int main()
{
double n = 4 *cos( fmod( acos(2.0/4.0), 2*3.14159265) );
std::cout << "Given the number " << n << std::endl;
// convert the given floating point value `n` into a
// normalized fraction and an integral power of two
int exp;
double mantissa = std::frexp(n, &exp);
// display results as Mantissa x 2^Exponent
std::cout << "We have " << n << " = "
<< mantissa << " * 2^" << exp << std::endl;
return 0;
}
I'm trying to compute a series using C++.
The series is:
(for those wondering)
My code is the following:
#include <iostream>
#include <fstream>
#include <cmath> // exp
#include <iomanip> //setprecision, setw
#include <limits> //numeric_limits (http://en.cppreference.com/w/cpp/types/numeric_limits)
long double SminOneCenter(long double gamma)
{
using std::endl; using std::cout;
long double result=0.0l;
for (long double k = 1; k < 1000 ; k++)
{
if(isinf(pow(1.0l+pow(gamma,k),6.0l/4.0l)))
{
cout << "infinity for reached for gamma equals: " << gamma << "value of k: " << k ;
cout << "maximum allowed: " << std::numeric_limits<long double>::max()<< endl;
break;
}
// CAS PAIR: -1^n = 1
if ((int)k%2 == 0)
{
result += pow(4.0l*pow(gamma,k),3.0l/4.0l) /(pow(1+pow(gamma,k)),6.0l/4.0l);
}
// CAS IMPAIR:-1^n = -1
else if ((int)k%2!=0)
{
result -= pow(4.0l*pow(gamma,k),3.0l/4.0l) /(pow(1+pow(gamma,k)),6.0l/4.0l);
//if (!isinf(pow(k,2.0l)*zeta/2.0l))
}
// cout << result << endl;
}
return 1.0l + 2.0l*result;
}
Output will be, for instance with gamma = 1.7 :
infinity reached for gamma equals: 1.7 value of k: 892
The maximum value a long double can represent, as provided by the STL numeric_limits, is: 1.18973e+4932.
However (1+1.7^892)= 2.19.... × 10^308 which is way lower than 10^4932, so it shouldn't be considered as infinity.
Provided my code is not wrong (but it very well might be), could anyone tell me why the discussed code evals to infinity when it should not?
You need to use powl rather than pow if you want to supply long double arguments.
Currently you are hitting the numeric_limits<double>::max() in your pow calls.
As an alternative, consider using std::pow which has appropriate overloads.
Reference http://en.cppreference.com/w/c/numeric/math/pow
Let's say that you have a function:
string function(){
double f = 2.48452
double g = 2
double h = 5482.48552
double i = -78.00
double j = 2.10
return x; // ***
}
* for x we insert:
if we will insert f, function returns: 2.48
if we will insert g, function returns: 2
if we will insert h, function returns: 5482.49
if we will insert i, function returns:-78
if we will insert j, function returns: 2.1
They are only example, who shows how the funcion() works. To precise:
The function for double k return rounded it to: k.XX,
but for:
k=2.20
it return 2.2 as string.
How it implements?
1) Just because you see two digits, it doesn't mean the underlying value was necessarily rounded to two digits.
The precision of the VALUE and the number of digits displayed in the FORMATTED OUTPUT are two completely different things.
2) If you're using cout, you can control formatting with "setprecision()":
http://www.cplusplus.com/reference/iomanip/setprecision/
EXAMPLE (from the above link):
// setprecision example
#include <iostream> // std::cout, std::fixed
#include <iomanip> // std::setprecision
int main () {
double f =3.14159;
std::cout << std::setprecision(5) << f << '\n';
std::cout << std::setprecision(9) << f << '\n';
std::cout << std::fixed;
std::cout << std::setprecision(5) << f << '\n';
std::cout << std::setprecision(9) << f << '\n';
return 0;
}
sample output:
3.1416
3.14159
3.14159
3.141590000
Mathematically, 2.2 is exactly the same as 2.20, 2.200, 2.2000, and so on. If you want to see more insignificant zeros, use [setprecision][1]:
cout << fixed << setprecision(2);
cout << 2.2 << endl; // Prints 2.20
To show up to 2 decimal places, but not showing trailing zeros you can do something such as:
std::string function(double value)
{
// get fractional part
double fracpart = value - static_cast<long>(value);
// compute fractional part rounded to 2 decimal places as an int
int decimal = static_cast<int>(100*fabs(fracpart) + 0.5);
if (decimal >= 100) decimal -= 100;
// adjust precision based on the number of trailing zeros
int precision = 2; // default 2 digits precision
if (0 == decimal) precision = 0; // 2 trailing zeros, don't show decimals
else if (0 == (decimal % 10)) precision = 1; // 1 trailing zero, keep 1 decimal place
// convert value to string
std::stringstream str;
str << std::fixed << std::setprecision(precision) << value;
return str.str();
}
My school give me an assignment to calculate pi.
The result should be :
Question 4
Accuracy set at : 1000
term pi
1 4
100 3.13159
200 3.13659
300 3.13826
400 ...
... ...
The result in my program :
term pi
1 4
100 3
200 3
300 3
400 ...
... ...
I guess that when I do (4 / denominator), the result will lose the decimal number although I have changed some declarations of data type from int to double.
(Some websites tell me to do this.)
Maybe I do it wrongly.
How can I deal with this problem?
The following is my program.
#include <iostream>
using namespace std;
class Four
{
private:
int inputedAccuracy;
double pi;
int denominator;
int doneTermCounter;
double oneTerm;
int negativeController;
public:
double question4()
{
cout << "Accuracy set at : " ;
cin >> inputedAccuracy;
cout << endl;
pi = 0.0;
denominator = 1.0;
doneTermCounter = 0;
negativeController = 1;
cout << "Term" << " " << "pi" << endl;
cout << "1 " << " " << "4" << endl;
for (inputedAccuracy; inputedAccuracy > 0; inputedAccuracy -= 100)
{
for (int doneTerm = 0; doneTerm < 100; doneTerm++)
{
pi = pi + (negativeController * 4 / denominator);
negativeController *= -1;
denominator += 2;
doneTermCounter++;
}
if (doneTermCounter >= 10000)
cout << doneTermCounter << " " << pi << endl;
else
if (doneTermCounter >= 1000)
cout << doneTermCounter << " " << pi << endl;
else
cout << doneTermCounter << " " << pi << endl;
}
return 0.0;
}
};
Thank you for your attention!
pi = pi + (negativeController * 4 / denominator);
The (negativeController * 4 / denominator) expression results in an int because both negativeController and denominator are int. In other words, you're doing an integer division here which explains why you don't get the expected result.
Declare either (or both) of them as double to force a floating-point division.
You should change :-
int denominator; to
double denominator;
See here
pi = pi + (negativeController * 4 / denominator);
In this line, you have an integer division (because both operands of / are of type int), meaning that the fractional part of the division's result is discarded.
To use floating point division, at least one operand/side needs to be of type float or (long) double. The easiest way to achieve this would in this case be a change of 4 (a literal of type int) to 4.0 (a literal of type double):
Then, when calculating the result of *, negativeController will also be converted to double (usual arithmetic conversions), yielding a double as the left-hand side operand of / which in turn causes denominator (the rhs) to also be converted into a double and so on.
I think changing negativeController and denominator to int would do the trick as the sub-expression is being evaluated on integers thus loosing precision.