Why do these two code snippets produce different results? (Float, Double precision) - c++

I am only beginning to learn C++ and have been messing around with float and double values. Below are two code snippets that seem to me to be doing the same thing but give different results. What am I missing? Can someone explain the precision error the first code must have to get a different result than the second.
int _tmain(int argc, _TCHAR* argv[])
{
const float f = 0.1;
const double d = 0.1;
int counter = 0;
for(counter; ((double)counter * f - (double)counter * d) < 0.34; counter++) {}
cout << "Iterations = " << counter << "\n" ;
system("pause");
return 0;
}
int main (int argc, const char * argv[])
{
float time_f = 0.1;
double time_d = 0.1;
float total_f = 0;
double total_d = 0;
int count=0;
double difference = 0;
while (true) {
total_d = count * time_d;
total_f = count * time_f;
if(total_f - total_d >= 0.34){
break;
}
count++;
}
std::cout << count << "\n";
system("pause");
}
I have altered the cast of my for loop condition between float and double but the value does not differ.

Both float and double have a finite representation, which means they
take on a series of descrete values, and not just any real value. In
particular, in your example, 0.1 has no exact floating point
representation on any modern machine I know of (all of which use a base
which is a power of 2 in their implementation—0.1 is 1/5 *
1/2, and nothing which is a multiple of 1/5 can have a finite
representation unless the base is a multiple of 5).
The result is that either float and double have the same underlying
representation (not usually the case), or there will be a difference as
soon as count is different from 0.
The usual reference for this subject is
“What
Every Computer Scientist Should Know About Floating-Point
Arithmetic”. Until you've read and understood (or at least
understood the implications) it, you shouldn't touch machine floating
point.

Difference between that two code snippets is in cast. counter * f is casted to double in first snippet and stored to float variable in second one.
Here's an example of how it could look like:
#include <stdio.h>
int main(int argc, char* argv[])
{
const float f = 0.1;
const double d = 0.1;
int count = 0;
for(count; (double)(count * f) - (double)(count * d) < 0.34; count++);
printf("Iterations = %d\n", count);
count = 0;
while (true)
{
double total_d = count * d; // is equal to (double)(count * d)
double total_f = count * f; // is equal to (double)(count * f)
if (total_f - total_d >= 0.34)
break;
count++;
}
printf("Iterations = %d\n", count);
return 0;
}

You haven't casted count to double here:
total_d = count * time_d;
total_f = count * time_f;
Another thing, those loops will never end since both subtraction operands have the same value :S

Related

How can I get a more accurate result when dividing numbers in C++

I am trying to estimate PI using C++ as a fun math project. I've run into an issues where I can only get it as precise as 6 decimal places.
I have tried using a float instead of a double but found the same result.
My code works by summing all the results of 1/n^2 where n=1 through to a defined limit. It then multiplies this result by 6 and takes the square root.
Here is a link to an image written out in mathematical notation
Here is my main function. PREC is the predefined limit. It will populate the array with the results of these fractions and get the sum. My guess is that the sqrt function is causing the issue where I cannot get more precise than 6 digits.
int main(int argc, char *argv[]) {
nthsums = new float[PREC];
for (int i = 1; i < PREC + 1; i += 1) {
nthsums[i] = nth_fraction(i);
}
float array_sum = sum_array(nthsums);
array_sum *= 6.000000D;
float result = sqrt(array_sum);
std::string resultString = std::to_string(result);
cout << resultString << "\n";
}
Just for the sake of it, I'll also include my sum function as I suspect that there could be something wrong with that, too.
float sum_array(float *array) {
float returnSum = 0;
for (int itter = 0; itter < PREC + 1; itter += 1) {
if (array[itter] >= 0) {
returnSum += array[itter];
}
}
return returnSum;
}
I would like to get at least as precise as 10 digits. Is there any way to do this in C++?
So even with long double as the floating point type used for this, there's some subtlety required because adding two long doubles of substantially different order of magnitudes can cause precision loss. See here for a discussion in Java but I believe it to be basically the same behavior in C++.
Code I used:
#include <iostream>
#include <cmath>
#include <numbers>
long double pSeriesApprox(unsigned long long t_terms)
{
long double pi_squared = 0.L;
for (unsigned long long i = t_terms; i >= 1; --i)
{
pi_squared += 6.L * (1.L / i) * (1.L / i);
}
return std::sqrtl(pi_squared);
}
int main(int, char[]) {
const long double pi = std::numbers::pi_v<long double>;
const unsigned long long num_terms = 10'000'000'000;
std::cout.precision(30);
std::cout << "Pi == " << pi << "\n\n";
std::cout << "Pi ~= " << pSeriesApprox(num_terms) << " after " << num_terms << " terms\n";
return 0;
}
Output:
Pi == 3.14159265358979311599796346854
Pi ~= 3.14159265349430016911469465413 after 10000000000 terms
9 decimal digits of accuracy, which is about what we'd expect from a series converging at this rate.
But if all I do is reverse the order the loop in pSeriesApprox goes, adding the exact same terms but from largest to smallest instead of smallest to largest:
long double pSeriesApprox(unsigned long long t_terms)
{
long double pi_squared = 0.L;
for (unsigned long long i = 1; i <= t_terms; ++i)
{
pi_squared += 6.L * (1.L / i) * (1.L / i);
}
return std::sqrtl(pi_squared);
}
Output:
Pi == 3.14159265358979311599796346854
Pi ~= 3.14159264365071688729358356795 after 10000000000 terms
Suddenly we're down to 7 digits of accuracy, even though we used 10 billion terms. In fact, after 100 million terms or so, the approximation to pi stabilizes at this specific value. So while using sufficiently large data types to store these computations is important, some additional care is still needed when trying to perform this kind of sum.

Power function in a loop

I need help with writing power function. So, I need to write a porogramm, that will output a table from 1 to 10 in a power in a LOOP. NOT USING POW or EXP
Example of output:
0^0 == 1
1^1 == 1
2^2 == 4
3^3 == 27
4^4 == 256
(and so on, up to)
10^10 == 10000000000
NOT USING Cmath (NO POW or EXP)
for example:
e.g. power( 3.0, 5 ) will return 243 because 3*3*3*3*3 is 243
e.g. power( 173, 0 ) will return 1 because any number raised to the power of 0 is 1.
I did this Simple loop, But I have no idea how to insert power formula in it. I was also thinking about while loop
#include <iostream>
#include <string>
using namespace std;
int main(){
int number = 0, tot;
for (int table = 0; table < 10; table++)
{
tot = number * table;
cout << tot << endl;
number++;
}
}
This is a recursive function that can calculate a value raised to an integer power
double power(double base, unsigned int exp)
{
if (exp == 0)
{
return 1.0;
}
else
{
return base * power(base, exp - 1);
}
}
An iterative method to do this would be
double power(double base, unsigned int exp)
{
double product = 1.0;
for (unsigned int i = 0; i < exp; ++i)
{
product *= base;
}
return product;
}
You can test either method with something like
int main()
{
std::cout << power(5, 3);
}
Output
125
I think you already know the answer to your own question by now, but still; some hints:
Exponentiation is a repeated multiplication of the base, the repetition is defined by the exponent.
In C++, or any modern programming language, loops allow repetition of certain blocks of code: when the number of iterations is known beforehand, use the for-loop, otherwise, use the while-loop.
Combining both hints: you'll need to use a loop to repeat a multiplication; the amount of repetition (or iterations) is known beforehand, thus, a for-loop will be best.
int exponentiation(int base, int exponent) {
int result = 1;
for (int i = 0; i < exponent; ++i)
result = result * base;
return result;
}
Note: this will only suffice for integer exponentiation with positive exponents!
You can then call this function in a for-loop to let it compute the values you want:
#include <iostream>
int main(int argc, char** argv) {
for(int i = 0; i <= 10; ++i)
std::cout << exponentiation(i, i) << '\n';
}

with given output, how many terms are used in the program calculation?

I have the following code which calculates, for the number of terms of your choosing, the square root of 6 * [ 1 + 1/(2^2) + 1/(3^2)....1/(n^2)]. In this case, I'm going with 100 terms. If I am given what the output should be, is there a way to, using my existing code, determine how many terms were used to get to that output?
#include <stdio.h>
#include <math.h>
int main(int argc, const char * argv[]) {
long double square = 0;
for (int i = 1; i <= 100; i++) {
long double squareExp = i*i;
square += 1/(squareExp);
}
long double sixTimes = 6 * square;
long double squareRoot = sqrt(sixTimes);
printf("%.8Lf", squareRoot);
return 0;
}
I tried making it so that I take the desired output (3.141592), squaring it and dividing by 6 to negative the square root and (*6), and tried running this code:
double temp = 3.141592 * 3.141592;
double tempB = temp / 6;
printf("%f\n", tempB);
int reachedZero = 0;
int valueOfN = 0;
long double square = 0;
while (square > 0) {
int i = 1;
square -= 1/i;
i++;
if (square <= 1) {
reachedZero = 1;
valueOfN = i;
break;
}
}
printf("%i", valueOfN);
return 0;
}
I can't figure out what to do. I want to take the number (after getting rid of the square root and multiplying by 6), and subtract numbers starting with 1, then 1/4, then 1/9, then 1/16...1/(n^2) until the number becomes negative. Once that happens, I set a flag and I know how many terms I needed to reach that #. I then set that specific counter to a variable, which I can print out.
#EugeneSh. This was a working solution for me. Basically matched the pi output I was looking for with my loop, checking it each time. Could have changed the for loop to a while loop but it works fine this way.
int main(int argc, const char * argv[]) {
long double square;
for (long i = 1; i>=1; i++) {
square += 1.0/(i*i);
long double sixTimes = sqrt(6 * square);
if (sixTimes >= 3.141592) {
printf("%li", i);
break;
}
}
return 0;
}

c++ convert a fractional part of a number into integer

I needed to convert a fractional part of a number into integer without a comma,
for example I have 3.35 I want to get just 35 part without zero or a comma,
Because I used the modf() function to extract the the fractional part but it gives me a 0.35
if there is any way to do that or to filter the '0.' part I will be very grateful if you show me how with the smaller code possible,
A bit more efficient than converting to a string and back again:
int fractional_part_as_int(double number, int number_of_decimal_places) {
double dummy;
double frac = modf(number,&dummy);
return round(frac*pow(10,number_of_decimal_places));
}
#include <iostream>
#include <cmath>
double round(double r) {
return (r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5);
}
double floor_to_zero(double f) {
return (f > 0.0) ? std::floor(f) : std::ceil(f);
}
double sign(double s) {
return (s < 0.0) ? -1.0 : 1.0;
}
int frac(double f, int prec) {
return round((f - floor_to_zero(f)) * prec) * sign(f);
}
int main() {
double a = 1.2345;
double b = -34.567;
std::cout << frac(a, 100) << " " << frac(b, 100) << std::endl; // 23 57
}
another solution
int precision= 100;
double number = 3.35;
int f = floor(xx);
double temp = ( f - number ) * -1;
int fractional_part = temp * precision;
IF you need it as a string, a quite easy C style solution would be (should work for variable number of decimal places):
double yourNumber = 0.35f;
char buffer[32];
snprintf(buffer, 32, "%g", yourNumber);
strtok(buffer, "."); // Here we would get the part before . , should still check
char* fraction = strtok(NULL, ".");
int fractionAsInt = atoi(fraction);
This example lacks error handling in case of a bad string and is not feasible if you just need a fixed number of decimal places, since the arithmetic approaches work better there.
Something like this should work:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
static int get_frac(double value, unsigned short precision)
{
return (int)((value - (long)value) * pow(10, precision));
}
static int get_frac_no_trailing_zeros(double value, unsigned short precision)
{
int v = get_frac(value, precision);
while (v % 10 == 0)
v /= 10;
return v;
}
int main(int argc, char *argv[])
{
double v;
v = 123.4564;
printf("%.4f = %d\n", v, get_frac(v, 2));
printf("%.4f = %d\n", v, get_frac(v, 4));
printf("%.4f = %d\n", v, get_frac(v, 6));
printf("%.4f = %d\n", v, get_frac_no_trailing_zeros(v, 6));
return EXIT_SUCCESS;
}
You may also want to either avoid calling pow by having a user supply a number in a power of 10 in a first place, or use a lookup table.
Using some stl magic, here is the sample code:
typedef std::pair<int, int> SplitFloat;
SplitFloat Split(float value, int precision)
{
// Get integer part.
float left = std::floor(value);
// Get decimal part.
float right = (value - left) * float(std::pow(10, precision));
return SplitFloat(left, right);
}
It can be improved, but is pretty straightforward.
I just did something close to what you are trying to do, though I'm still pretty new. None the less, maybe this will help someone in the future as I landed here looking for results for my problem.
The first step is making sure that the variable that contains 3.35 is a double, but that's probably obvious.
Next, create a variable that is only an integer and set it's value equal to the value of the double. It will then only contain the whole number.
Then subtract the whole number (int) from the double. You will be left with the fraction/decimal value. From there, just multiply by 100.
Beyond the 100ths decimal value, you would have to do a little more configuring obviously, but it should be fairly simple to do with an if statement. If the decimal value is greater than .99, multiply 1000 instead etc..
Here's how I would do it.
#include <sstream>
#include <string>
int main()
{
double d = yourDesiredNumber; //this is your number
std::ostringstream out;
out << setprecision(yourDesiredPrecision) << std::fixed
<< std::showpoint << d;
std::istringstream in(out.str());
std::string wholePart; //you won't need this.
int fractionalPart;
std::getline(in, wholePart, '.');
in >> fractionalPart;
//now fractionalPart contains your desired value.
}
I'm pretty sure that instead of two different istringstream and ostringstream objects you could have gotten away with just one stringstream object, but I am not sure about the details (never used that class) so I didn't use it in the example.

A C routine to round a float to n significant digits?

Suppose I have a float. I would like to round it to a certain number of significant digits.
In my case n=6.
So say float was f=1.23456999;
round(f,6) would give 1.23457
f=123456.0001 would give 123456
Anybody know such a routine ?
Here it works on website: http://ostermiller.org/calc/significant_figures.html
Multiply the number by a suitable scaling factor to move all significant digits to the left of the decimal point. Then round and finally reverse the operation:
#include <math.h>
double round_to_digits(double value, int digits)
{
if (value == 0.0) // otherwise it will return 'nan' due to the log10() of zero
return 0.0;
double factor = pow(10.0, digits - ceil(log10(fabs(value))));
return round(value * factor) / factor;
}
Tested: http://ideone.com/fH5ebt
Buts as #PascalCuoq pointed out: the rounded value may not exactly representable as a floating point value.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *Round(float f, int d)
{
char buf[16];
sprintf(buf, "%.*g", d, f);
return strdup(buf);
}
int main(void)
{
char *r = Round(1.23456999, 6);
printf("%s\n", r);
free(r);
}
Output is:
1.23457
Something like this should work:
double round_to_n_digits(double x, int n)
{
double scale = pow(10.0, ceil(log10(fabs(x))) + n);
return round(x * scale) / scale;
}
Alternatively you could just use sprintf/atof to convert to a string and back again:
double round_to_n_digits(double x, int n)
{
char buff[32];
sprintf(buff, "%.*g", n, x);
return atof(buff);
}
Test code for both of the above functions: http://ideone.com/oMzQZZ
Note that in some cases incorrect rounding may be observed, e.g. as pointed out by #clearScreen in the comments below, 13127.15 is rounded to 13127.1 instead of
13127.2.
This should work (except the noise given by floating point precision):
#include <stdio.h>
#include <math.h>
double dround(double a, int ndigits);
double dround(double a, int ndigits) {
int exp_base10 = round(log10(a));
double man_base10 = a*pow(10.0,-exp_base10);
double factor = pow(10.0,-ndigits+1);
double truncated_man_base10 = man_base10 - fmod(man_base10,factor);
double rounded_remainder = fmod(man_base10,factor)/factor;
rounded_remainder = rounded_remainder > 0.5 ? 1.0*factor : 0.0;
return (truncated_man_base10 + rounded_remainder)*pow(10.0,exp_base10) ;
}
int main() {
double a = 1.23456999;
double b = 123456.0001;
printf("%12.12f\n",dround(a,6));
printf("%12.12f\n",dround(b,6));
return 0;
}
If you want to print a float to a string use simple sprintf(). For outputting it just to the console you can use printf():
printf("My float is %.6f", myfloat);
This will output your float with 6 decimal places.
Print to 16 significant digit.
double x = -1932970.8299999994;
char buff[100];
snprintf(buff, sizeof(buff), "%.16g", x);
std::string buffAsStdStr = buff;
std::cout << std::endl << buffAsStdStr ;