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++)
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
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.
I would like to print a double value, into a string of no more than 8 characters. The printed number should have as many digits as possible, e.g.
5.259675
48920568
8.514e-6
-9.4e-12
I tried C++ iostreams, and printf-style, and neither respects the provided size in the way I would like it to:
cout << setw(8) << 1.0 / 17777.0 << endl;
printf( "%8g\n", 1.0 / 17777.0 );
gives:
5.62525e-005
5.62525e-005
I know I can specify a precision, but I would have to provide a very small precision here, in order to cover the worst case. Any ideas how to enforce an exact field width without sacrificing too much precision? I need this for printing matrices. Do I really have to come up with my own conversion function?
A similar question has been asked 5 years ago: Convert double to String with fixed width , without a satisfying answer. I sure hope there has been some progress in the meantime.
This seems not too difficult, actually, although you can't do it in a single function call. The number of character places used by the exponent is really quite easy to predict:
const char* format;
if (value > 0) {
if (value < 10e-100) format = "%.1e";
else if (value < 10e-10) format = "%.2e";
else if (value < 1e-5) format = "%.3e";
}
and so on.
Only, the C standard, where the behavior of printf is defined, insists on at least two digits for the exponent, so it wastes some there. See c++ how to get "one digit exponent" with printf
Incorporating those fixes is going to make the code fairly complex, although still not as bad as doing the conversion yourself.
If you want to convert to fixed decimal numbers (e.g. drop the +/-"E" part), then it makes it a lot easier to accomplish:
#include <stdio.h>
#include <cstring> // strcpy
#include <iostream> // std::cout, std::fixed
#include <iomanip> // std::setprecision
#include <new>
char *ToDecimal(double val, int maxChars)
{
std::ostringstream buffer;
buffer << std::fixed << std::setprecision(maxChars-2) << val;
std::string result = buffer.str();
size_t i = result.find_last_not_of('\0');
if (i > maxChars) i = maxChars;
if (result[i] != '.') ++i;
result.erase(i);
char *doubleStr = new char[result.length() + 1];
strcpy(doubleStr, (const char*)result.c_str());
return doubleStr;
}
int main()
{
std::cout << ToDecimal(1.26743237e+015, 8) << std::endl;
std::cout << ToDecimal(-1.0, 8) << std::endl;
std::cout << ToDecimal(3.40282347e+38, 8) << std::endl;
std::cout << ToDecimal(1.17549435e-38, 8) << std::endl;
std::cout << ToDecimal(-1E4, 8) << std::endl;
std::cout << ToDecimal(12.78e-2, 8) << std::endl;
}
Output:
12674323
-1
34028234
0.000000
-10000
0.127800