Auto Rounding From Something While Dividing and Multiplying - c++

#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.

Related

How to find first pi beginning with 3.14159

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.

What does double store?

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;
}

Long double overflows but value smaller than maximum representable value

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

separating decimal points into two integers

I have been given double x = 23.456; and two integer d and c.
I have to break it so that d gets the value 23 and c gets the value 456.
I thought of the following:-
int d;
d=(int)x;
but I cannot think of what to do with c as it is an integer and if i write
c=(x-d)*1000;
then it might be applicable for this case only and not for any other case.
Is there any way to get the number of digits after the decimal and then multiply it with equal number of zeros.
Please help!!!
You could repeatedly multiply it by 10, until there is nothing after decimal point.
double c = x - d;
while(c - floor(c) > 0.0)
{c *= 10;}
you may also need to #include <math.h> for floor function, which rounds down a number. e.g. floor(4.9) returns 4.0
Floating point calculations are little bit tricky in C++ (same is true for Java and other languages). You should avoid their direct comparison and do some other stuff to get predictable result when using them, consider:
double d1=1.1;
double d2= d1 / 10.0;
if(d2==0.11)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
d1=1.99;
float f1=0.01f;
double d3=d1+f1;
if(d3==2.0)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
d1=1.99;
d2=0.01;
d3=d1+d2-2.0;
if(d3==0.0)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
As for practical solution of the problem I can suggest 2 variants:
Var 1 is to use a function that allows to specify number of digits:
#include <iostream>
#include <cmath>
using namespace std;
void split_double(const double value, int& i_part, int& r_part,
const int max_digits_after_dp, int min_digits_after_dp){
auto powerOfTenL = [](int power){ int result = 1;
for(int i=0;i<power;++i)result *= 10;
return result;
};
//Get integral part
i_part = (int)value;
double temp = (value-i_part);
double pOfTen = powerOfTenL(max_digits_after_dp);
temp *= pOfTen;
//Get real part
r_part = round(temp);
//Remove zeroes at the right in real part
int num_of_d = max_digits_after_dp;
if(min_digits_after_dp>max_digits_after_dp)
min_digits_after_dp=max_digits_after_dp;
while (num_of_d>min_digits_after_dp) {
//If the number is divisible by 10, divide it by 10
if(0==(r_part%10)) { r_part /=10; num_of_d--;
}
else break; //Last digit is not 0
}
}
int main(int argc, char *argv[])
{
double value = 10.120019;
int ipart,rpart;
const int digitsMax = 6;
const int digitsMin = 3;
split_double(value,ipart,rpart,digitsMax,digitsMin);
cout<<"Double " <<value << " has integral part " <<ipart
<<" and real part "<<rpart<<endl;
return 0;
}
Second variant to solve the problem is to use C/C++ formatting functions like vsprintf and then split the resulting string.

C++ Addition Not Working

I wrote up a solution for a Google Code Jam problem as demonstrated:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <cmath>
using namespace std;
int main(int argc, char** argv) {
ifstream in;
in.open(argv[1]);
int t, c = 0;
in >> t;
while(c++<t) {
string msg;
in >> msg;
map<char,int> m;
int base = 0;
for(char& ch : msg) {
if(!m[ch]) {
base++;
m[ch] = base == 1 ? base : (base == 2 ? -1 : base - 1);
}
}
if(base < 2)
base = 2;
double total = 0;
double p = pow(base, msg.size()-1);
for(char& ch : msg) {
if(m[ch] != -1) {
if(c == 37) cout << "total=" << total << "+" << (m[ch] * p) << "=" << total + (m[ch] * p) << endl;
total = total + (m[ch] * p);
}
p /= base;
}
cout.precision(0);
cout << fixed << "Case #" << c << ": " << total << endl;
}
in.close();
return 0;
}
As you can see I have some debug statements being printed out for case 37 because some weird stuff happen there:
Case #36: 1000000000000000000
total=0+450283905890997376=450283905890997376
total=450283905890997376+100063090197999424=550346996088996800
total=550346996088996800+16677181699666570=567024177788663360
total=567024177788663360+5559060566555523=572583238355218880
total=572583238355218880+1853020188851841=574436258544070720
total=574436258544070720+1235346792567894=575671605336638592
total=575671605336638592+205891132094649=575877496468733248
total=575877496468733248+68630377364883=575946126846098112
total=575946126846098112+22876792454961=575969003638553088
total=575969003638553088+15251194969974=575984254833523072
total=575984254833523072+847288609443=575985102122132544
total=575985102122132544+564859072962=575985666981205504
total=575985666981205504+62762119218=575985729743324736
total=575985729743324736+20920706406=575985750664031168
total=575985750664031168+6973568802=575985757637600000
total=575985757637600000+129140163=575985757766740160
total=575985757766740160+28697814=575985757795437952
total=575985757795437952+1594323=575985757797032256
total=575985757797032256+177147=575985757797209408
total=575985757797209408+59049=575985757797268480
total=575985757797268480+6561=575985757797275072
total=575985757797275072+4374=575985757797279424
total=575985757797279424+729=575985757797280128
total=575985757797280128+81=575985757797280192
total=575985757797280192+2=575985757797280192
Case #37: 575985757797280192
As you can see, at some point the addition just works incorrectly (e.g 575985757797279424+729 = 575985757797280153 not 575985757797280128)
I'm incredibly dumbfounded by this behavior and would greatly appreciate any possible explanation.
You've reached the limits of precision for your chosen floating-point type.
If you insist on avoiding integers (i.e. fixed point), you'll need an arbitrary-precision numerical library to best it. You should also read The Floating-Point Guide before continuing to use these features.
However, the figures you have here would all fit into a 64-bit integer. Why not just use that and save yourself some trouble?
Double has 3 components sign,exponent,fraction.
For example 1.2345 is represented as 12345*10power-4
Even though Double has size as long long it has some bits dedicated for exponent part so the precision is less than that of long long which gives float an accuracy of 7 decimal digits and double an accuracy of 16 decimal digits.Since floating point arithmetic are not precise after specified number of digits
Also read
1.https://chortle.ccsu.edu/java5/Notes/chap11/ch11_2.html
2.http://codeforces.com/blog/entry/1521?#comment-28329 (about pow in c++)