Here is my code:
double round( char* strNumber, int decPlace);
int main()
{
int decimal;
char initialNumber[256];
cout << "Enter decimal and number " << endl;
cin >> decimal;
cin >> initialNumber;
cout << setprecision (15) << round ( initialNumber,decimal ) << endl;
return 0;
}
double round( char* strNumber, int decPlace)//
{
double number = atof(strNumber);
int temp = ( int ) ( pow(10.0,decPlace) * number + 0.5 );
double result = ( double ) temp / pow(10.0,decPlace);
return result;
}
It works up to 6 decimal places. Otherwise it gives some strange result. Below are numbers that I used for testing and the output:
Test 1-round to 7 decimal places
105.265
52.5689745694
25.6835
452.689785
12.456789877458
Output
105.265
52.5689746
25.6835
-214.7483648
12.4567899
Test 1-round to 8 decimal places
The same numbers as previously
Output
-21.47483648
-21.47483648
-21.47483648
-21.47483648
12.45678988
As others have said, the cast to int won't work with large numbers. You could consider using floor instead, and keeping the number to be rounded in a double:
#include <cstdlib>
#include <cmath>
double round( char* strNumber, int decPlace)
{
double number = std::atof(strNumber);
double expo = std::pow(10.0,decPlace);
return std::floor( expo * number + 0.5) / expo;
}
int can hold a smaller range than double; on many platforms its maximum value is about 2 billion, which is less than pow(10.0,8) * number for most of your input numbers.
You could keep your number as a double and use floor to round down to an integer:
double temp = floor( pow(10.0,decPlace) * number + 0.5 );
double result = temp / pow(10.0,decPlace);
Looks to me like overflow. pow(10.0,decPlace) * number is a pretty large number - too large to fit in a 32 bit integer (which is what int probably is on your platform).
int temp = ( int ) ( pow(10.0,decPlace) * number + 0.5 );
temp is probably 32 bits. It can hold up about +- 2 billion. Overflow.
Related
I have a c++ program which calculates Pi but then its value gets cut off after a few decimal places because of the decimal place limit on the float which Pi is stored in.
I've already tried using different data types instead of float but they still have a decimal place limit which is too small.
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(){
cout << "Calculate Pi using the Nilakantha series" << endl << endl;
unsigned long int iterations = 0;
unsigned long int x = 0;
unsigned long int y = 2;
char z = 0;
string fileName = "";
int64_t Pi = {3.0f};
cout << "Input the number of loop iterations(maximum of 4,294,967,295): ";
cin >> iterations;
cout << "Input the name of the file you want to write to: ";
cin >> fileName;
for(x = 0; x < iterations; x++){
Pi += 4.0f / (y * (y + 1.0f) * (y + 2.0f));
y += 2;
Pi -= 4.0f / (y * (y + 1.0f) * (y + 2.0f));
y += 2;
}
ofstream file;
file.open(fileName + ".txt");
file << Pi;
file.close();
cout << endl << "Calculation complete, check the file " << fileName << ".txt";
cin >> z;
}
How do I remove the limit or use a method which stores the value of Pi without it getting cut off after a few decimal places?
There are a few big issues here. The first is that you're using std::cout to print the value, and std::cout only prints 6 digits by default. The second is that you declared Pi as an int64_t. That means you'll get at most 1 digit of precision, since Pi is an integer. You need to have it as a floating point type.
So how many digits will you get from each type?
6 digits from float
15-16 digits from double
20 digits from long double on clang and gcc, but only 15-16 in Visual Studio
Around 30 digits from GCC's __float128, although that one only works on GCC
If you want more precision than that, you're going to have to use a high-precision arithmetic library that gives you more digits by simulating it. It won't be as fast, but it'll do the job.
You can play around with the amount of precision with each type using this code. I templated calculatePi on the type, so you can just stick in float, double, long double, or __float128. It'll print 20 digits. This code should print all 20 digits correctly for __float128.
#include <cstdio>
using namespace std;
template<class Float>
Float calculatePi(size_t iterations) {
Float y = 2;
Float Pi = 3;
const Float two = 2;
const Float four = 4;
const Float one = 1;
for(size_t i = 0; i < iterations; i++) {
Pi += four / (y * (y + one) * (y + two));
y += two;
Pi -= four / (y * (y + one) * (y + two));
y += two;
}
return Pi;
}
int main(){
long double result = calculatePi<long double>(1000000);
printf("Expected: 3.14159265358979323846\n");
printf("Actual: %.20Lf", result);
}
(I'm ignoring some of the less fundamental issues which #JAntonioPerez points out in his fine answer and focusing on what I find to be the core of this question.)
If you just need a few more decimal digits of precision, then use double or long double instead of float.
If you want much higher precision, or a precision which can be specified as a run-time or compile-time arbitrary value, then you need something else. Either:
Use an arbitrary-precision number data type; here is a list of libraries providing such types.
Instead of iterating over the entire number, use iteration to determine the value of individual digits/characters in the output; and write the digits you obtain to the output file one at a time (or a few at a time).
Of course, both options are rather involved and are probably not appropriate for a "toy program" like you seem to be writing.
I am trying to extract 20 decimals from a variable, but there should be an error with the divide operation, as this program gives me a wrong result:
#include <iostream>
#include <cmath>
using namespace std;
int fracpart(long double input)
{
long long I;
I = input * 10;
return I % 10;
}
int main()
{
int n = 9, m = 450;
long double S;
S = (long double)n/m;
for(int i=1; i<=20; i++){
cout << fracpart(S) << " ";
S *= 10;
}
return 0;
}
What I get:
0 1 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
What I should get:
0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
You can check the base used by the representation of floating-point types inspecting the value of the macro constant FLT_RADIX (defined in header <cfloat>). As you probably already know, the binary system is used internally by the majority of modern computers, rather then the decimal one.
Now consider a rational number like 1/3. It can't be represented by a finite number of digits in base 10, you'll end up with some approximation, like 0.3333333 and an acceptable error. Note that the same number can be represented in a base 3 system with a finite number of digits (0.1).
The number you are trying to print, 9/450, has a "nice" base 10 representation, 0.02, but it can't be represented in base 2 with absolute precision, even if the division could be performed without adding any error. Don't be misleaded by that '2', consider that 0.02 = 2/100 = 1/50 = 1/(2 * 52), where 1/5 can only be approximated, in base 2.
Anyways, there are methods to achieve what you want, for example using the output manipulators std::setprecision and std::fixed (defined in header <iomanip>) or even writing a (really ugly) custom function. Take a look at the output of this program:
#include <iostream>
#include <cmath>
#include <iomanip>
#include <vector>
#include <cstdint>
// splits a number into its integral and fractional (a vector of digits) parts
std::vector<uint8_t> to_digits (
long double x, uint8_t precision, long double &integral
);
// Reconstructs the approximated number
long double from_digits (
long double integral_part, std::vector<uint8_t> &fractional_part
);
int main()
{
using std::cout;
int n = 9, m = 450;
long double S;
S = static_cast<long double>(n)/m;
cout << "\nBase 10 representation of calculated value:\n"
<< std::setprecision(70) << S << '\n';
// This ^^^^^^^^^^^^^^^^^^^^^ will change only how the value is
// printed, not its internal binary representation
cout << "\nBase 10 representation of literal:\n"
<< 0.02L << '\n';
// This ^^^^^ will print the exact same digits
// the next greater representable value is a worse approximation
cout << "\nNext representable value:\n"
<< std::nextafter(S, 1.0) << '\n';
// but you can try to obtain a "better" output
cout << "\nRounded representation printed using <iomanip> functions:\n"
<< std::setprecision(20) << std::fixed << S << '\n';
cout << "\nRounded fractional part printed using custom function:\n";
long double integral_part;
auto dd = to_digits(S, 20, integral_part);
for (auto const d : dd)
{
cout << static_cast<int>(d);
}
cout << '\n';
// Reversing the process...
cout << "\nApproximated value (using custom function):\n";
auto X = from_digits(integral_part, dd);
cout << std::setprecision(70) << std::fixed << X << '\n';
cout << std::setprecision(20) << std::fixed << X << '\n';
}
std::vector<uint8_t> to_digits (
long double x, uint8_t precision, long double &integral
)
{
std::vector<uint8_t> digits;
long double fractional = std::modf(x, &integral);
for ( uint8_t i = 0; i < precision; ++i )
{
long double digit;
fractional = std::modf(fractional * 10, &digit);
digits.push_back(digit);
}
if ( digits.size() && std::round(fractional) == 1.0L )
{
uint8_t i = digits.size();
while ( i )
{
--i;
if ( digits[i] < 9 )
{
++digits[i];
break;
}
digits[i] = 0;
if ( i == 0 )
{
integral += 1.0L;
break;
}
}
}
return digits;
}
long double from_digits (
long double integral_part, std::vector<uint8_t> &fractional_part
)
{
long double x = 1.0L;
for ( auto d : fractional_part )
{
x *= 10.0L;
integral_part += d / x;
}
return integral_part;
}
I Thought it has happening "because the binary division is not perfectly conversible to decimal numbers", but Bob__ was right! The problem is happening because the long long variable is kind of "problematic". So, I just changed the code and used the functions ceil and round that I mentioned. This time I have tested the code, so I hope that it satisfy your needs.
PS1: Extract the function was really necessary.
PS2: Don't forget to include math.h library.
PS3: And, sorry for the delay in answer.
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int main()
{
int n = 9, m = 450;
long double S;
S = (long double)n/m;
for(int i=1; i<=20; i++){
cout << fmod(round(fmod(S * 10,10)), 10) << " ";
S *= 10;
}
return 0;
}
Here is some examples: http://www.cplusplus.com/reference/cmath/trunc/
I am trying to count series of: 1/2 + 1/3 + 1/4 + 1/5 + ...
But I had problem with my output:
Insert how many series's number will be counted : 3 // I am input 3
Total = 1 // This is the problem, the output should shown = 1.8333
My program
#include <iostream>
#include <math.h>
using namespace std;
int recursion ( int n );
int main ()
{
int n;
cout << "Insert how many number will be counted : ";cin >> n;
cout << "Total = " << recursion(n);
}
int recursion (int a)
{
int result;
if ( a >= 1 )
{
result = 1;
}
else
{
result = ( pow ( a , -1 ) + recursion ( pow ( ( a - 1 ) , -1 ) ) );
}
return (result);
}
As others have said, use floating point types, such as double or float.
In integer division, 1/3 == 0.
Here's an iterative example:
const unsigned int NUMBER_OF_TERMS = 100;
double result = 0.0;
double denominator = 2.0;
for (unsigned int i = 0; i < NUMBER_OF_TERMS; ++i)
{
result = result + 1.0 / denominator;
denominator = denomenator + 1.0;
}
Your code should use floating point constants (with decimal points) and floating point variables (of type double or float).
Edit 1: Basic recursion
In some cases of recursion, thinking of the solution backwards may help the implementation.
For example, the series starts with 1.0/2.0. However, since the sum operation doesn't depend on order, we can start with 1.0/5.0 and work backwards:
result = 1.0/5.0 + 1.0/4.0 + 1.0/3.0 + 1.0/2.0
This allows the denominator to be used as the condition for ending the recursion.
double recursive_sum(double denominator)
{
if (denominator < 2)
{
return 0.0;
}
return recursive_sum(denominator - 1.0)
+ 1.0 / denominator;
}
My task is to ask the user to how many decimal places of accuracy they want the summation to iterate compared to the actual value of pi. So 2 decimal places would stop when the loop reaches 3.14. I have a complete program, but I am unsure if it actually works as intended. I have checked for 0 and 1 decimal places with a calculator and they seem to work, but I don't want to assume it works for all of them. Also my code may be a little clumsy since were are still learning the basics. We only just learned loops and nested loops. If there are any obvious mistakes or parts that could be cleaned up, I would appreciate any input.
Edit: I only needed to have this work for up to five decimal places. That is why my value of pi was not precise. Sorry for the misunderstanding.
#include <iostream>
#include <cmath>
using namespace std;
int main() {
const double PI = 3.141592;
int n, sign = 1;
double sum = 0,test,m;
cout << "This program determines how many iterations of the infinite series for\n"
"pi is needed to get with 'n' decimal places of the true value of pi.\n"
"How many decimal places of accuracy should there be?" << endl;
cin >> n;
double p = PI * pow(10.0, n);
p = static_cast<double>(static_cast<int>(p) / pow(10, n));
int counter = 0;
bool stop = false;
for (double i = 1;!stop;i = i+2) {
sum = sum + (1.0/ i) * sign;
sign = -sign;
counter++;
test = (4 * sum) * pow(10.0,n);
test = static_cast<double>(static_cast<int>(test) / pow(10, n));
if (test == p)
stop = true;
}
cout << "The series was iterated " << counter<< " times and reached the value of pi\nwithin "<< n << " decimal places." << endl;
return 0;
}
One of the problems of the Leibniz summation is that it has an extremely low convergence rate, as it exhibits sublinear convergence. In your program you also compare a calculated extimation of π with a given value (a 6 digits approximation), while the point of the summation should be to find out the right figures.
You can slightly modify your code to make it terminate the calculation if the wanted digit doesn't change between iterations (I also added a max number of iterations check). Remember that you are using doubles not unlimited precision numbers and sooner or later rounding errors will affect the calculation. As a matter of fact, the real limitation of this code is the number of iterations it takes (2,428,700,925 to obtain 3.141592653).
#include <iostream>
#include <cmath>
#include <iomanip>
using std::cout;
// this will take a long long time...
const unsigned long long int MAX_ITER = 100000000000;
int main() {
int n;
cout << "This program determines how many iterations of the infinite series for\n"
"pi is needed to get with 'n' decimal places of the true value of pi.\n"
"How many decimal places of accuracy should there be?\n";
std::cin >> n;
// precalculate some values
double factor = pow(10.0,n);
double inv_factor = 1.0 / factor;
double quad_factor = 4.0 * factor;
long long int test = 0, old_test = 0, sign = 1;
unsigned long long int count = 0;
double sum = 0;
for ( long long int i = 1; count < MAX_ITER; i += 2 ) {
sum += 1.0 / (i * sign);
sign = -sign;
old_test = test;
test = static_cast<long long int>(sum * quad_factor);
++count;
// perform the test on integer values
if ( test == old_test ) {
cout << "Reached the value of Pi within "<< n << " decimal places.\n";
break;
}
}
double pi_leibniz = static_cast<double>(inv_factor * test);
cout << "Pi = " << std::setprecision(n+1) << pi_leibniz << '\n';
cout << "The series was iterated " << count << " times\n";
return 0;
}
I have summarized the results of several runs in this table:
digits Pi iterations
---------------------------------------
0 3 8
1 3.1 26
2 3.14 628
3 3.141 2,455
4 3.1415 136,121
5 3.14159 376,848
6 3.141592 2,886,751
7 3.1415926 21,547,007
8 3.14159265 278,609,764
9 3.141592653 2,428,700,925
10 3.1415926535 87,312,058,383
Your program will never terminate, because test==p will never be true. This is a comparison between two double-precision numbers that are calculated differently. Due to round-off errors, they will not be identical, even if you run an infinite number of iterations, and your math is correct (and right now it isn't, because the value of PI in your program is not accurate).
To help you figure out what's going on, print the value of test in each iteration, as well as the distance between test and pi, as follows:
#include<iostream>
using namespace std;
void main() {
double pi = atan(1.0) * 4; // Make sure you have a precise value of PI
double sign = 1.0, sum = 0.0;
for (int i = 1; i < 1000; i += 2) {
sum = sum + (1.0 / i) * sign;
sign = -sign;
double test = 4 * sum;
cout << test << " " << fabs(test - pi) << "\n";
}
}
After you make sure the program works well, change the stopping condition eventually to be based on the distance between test and pi.
for (int i=1; fabs(test-pi)>epsilon; i+=2)
I have this static method, it receives a double and "cuts" its fractional tail leaving two digits after the dot. works almost all the time. I have noticed that when
it receives 2.3 it turns it to 2.29. This does not happen for 0.3, 1.3, 3.3, 4.3 and 102.3.
Code basically multiplies the number by 100 uses modf divides the integer value by 100 and returns it.
Here the code catches this one specific number and prints out:
static double dRound(double number) {
bool c = false;
if (number == 2.3)
c = true;
int factor = pow(10, 2);
number *= factor;
if (c) {
cout << " number *= factor : " << number << endl;
//number = 230;// When this is not marked as comment the code works well.
}
double returnVal;
if (c){
cout << " fractional : " << modf(number, &returnVal) << endl;
cout << " integer : " <<returnVal << endl;
}
modf(number, &returnVal);
return returnVal / factor;
}
it prints out:
number *= factor : 230
fractional : 1
integer : 229
Does anybody know why this is happening and how can i fix this?
Thank you, and have a great weekend.
Remember floating point number cannot represent decimal numbers exactly. 2.3 * 100 actually gives 229.99999999999997. Thus modf returns 229 and 0.9999999999999716.
However, cout's format will only display floating point numbers to 6 decimal places by default. So the 0.9999999999999716 is shown as 1.
You could use (roughly) the upper error limit that a value represents in floating point to avoid the 2.3 error:
#include <cmath>
#include <limits>
static double dRound(double d) {
double inf = copysign(std::numeric_limits<double>::infinity(), d);
double theNumberAfter = nextafter(d, inf);
double epsilon = theNumberAfter - d;
int factor = 100;
d *= factor;
epsilon *= factor/2;
d += epsilon;
double returnVal;
modf(number, &returnVal);
return returnVal / factor;
}
Result: http://www.ideone.com/ywmua
Here is a way without rounding:
double double_cut(double d)
{
long long x = d * 100;
return x/100.0;
}
Even if you want rounding according to 3rd digit after decimal point, here is a solution:
double double_cut_round(double d)
{
long long x = d * 1000;
if (x > 0)
x += 5;
else
x -= 5;
return x / 1000.0;
}