C++ significant figures
Asked Answered
A

7

9

How can I do math involving significant figures in C++? I want this to work correct with measured data from chemistry and physics experiments. An example: 65 / 5 = 10. I would need to get rid of unneeded decimal places and replace some digits with 0s.

Thanks!

Apothegm answered 5/1, 2011 at 17:58 Comment(7)
5., 5.0, 5.00000000 are the same in the computer's representation. Are you talking about how to display the result with 2 significant figures?Harbourage
Yes, I am. I will edit my post to say that.Apothegm
I assume he means in circumstances where its 3.5 * 1.00 * pi he wants it to calculate using 3.5 * 1.0 * 3.1 (unless I am confused)Polysemy
@Kenny: I would guess he wants to keep track of the precision, using the number of digits. So 5 would mean an error of +-0.5, while 5.0 would mean an error of +-0.05.Feudality
I really hope 6.00 1.20 and 5.00 do not represent money amounts !Bushwhacker
Basically, I want to use this in a c++ program to do my physics and chemistry homework for me. I need to deal with the significant digits though.Apothegm
@joshim5: you'd be better with interval arithmetic. Even significant digits are error prone: basically, when you add 2.3 + 3.4, the result is between 5.6 and 5.8, when you substract 3342 - 3341, result is between 0 and 2.Bushwhacker
W
-2

Well there are good math libraries in math.h

Also storing your figures in floats, doubles or long doubles will allow for more precise operations.

Floats offer 7 significant digits while doubles offer 16 significant digits.

source

Also when printing out usually people use _snprintf or printf and you can format those doubles, floats to the precision you want like:

Float Precision

printf("Value %8.2f", floatVariable);

This says you require a total field of 8 characters, within the 8 characters the last 2 will hold the decimal part.

_snprintf(buffer, sizeof(buffer), "Value %.2f", floatVariable);

The example above requests the minimum field width and the last two characters are to hold the decimal part.

Westsouthwest answered 5/1, 2011 at 18:3 Comment(1)
Those are “digits after the decimal point”, not significant figures. For scientists and engineers there’s a very important difference between the two.Drawstring
B
9

This should get you what you need:

std::cout.precision(x); // x would be the number of significant figures to output
Bronchia answered 5/1, 2011 at 18:1 Comment(2)
would I write: cout.precision(2) << 5.34343; if I wanted to display 5.3?Apothegm
Correct - here's there documentation on it: cplusplus.com/reference/iostream/ios_base/precisionBronchia
B
4

This may not be the most efficient way, but you can create a custom sig fig data type.

class SigFigFloat
{
  SigFigFloat(vector<short> digits, int decimalIndex, bool negative);
  SigFigFloat operator+(const SigFigFloat &value);
  SigFigFloat operator-(const SigFigFloat &value);
  //etc...


}

It can be a lot of work, but if you implement this right, it can be a really flexible way to represent and do calculations with sig figs.

Bonnard answered 5/1, 2011 at 18:3 Comment(1)
If I were doing this, I wouldn't track just significant figures, I'd track the error range, not just the number of significant figures. That would allow me to work with figures like 123±0.2 or 123±0.7, while significant figures only allow for figures like 123±0.5Evvy
B
1

It is hard because significant figures are a decimal concept, and computers speak binary. You can use decimal number classes (I don't know of any), or use boost::interval, which is the closest to what you certainly want to achieve.

Bushwhacker answered 5/1, 2011 at 18:3 Comment(1)
+1 for suggesting interval arithmetic, though it may be overkill here, it's still something worth knowing about :)Geometry
S
1

That depends on how you are displaying them. If you are using the printf-family, you set the precision (sprintf(buffer, "%.2f", myfloat)). If you are using ostreams, you call the precision function to set the number of decimal places. If you are looking for the more scientific method of sig figs, you'll have to write a custom function that determines the precision based on the current value of the float.

Swell answered 5/1, 2011 at 18:6 Comment(0)
S
0

here is a quick C++11 solution that worked for me:

int sig_figs = 3;
double number = 1562.654478;

std::cout << "original number:" << number << std::endl;

number = ([number](int number_of_sig_figs)->double{
    std::stringstream lStream;
    lStream << std::setprecision(number_of_sig_figs) << number;
    return std::stod(lStream.str());
})(sig_figs);

std::cout << "rounded number:" << number << std::endl;
Snowflake answered 9/9, 2014 at 21:33 Comment(0)
G
0

Now that C++20 officially supports the std::format class, you can get printf-style formatting within C++:

#include <iostream>
#include <format>
    
int main()
{
    double d = 0.1 + 0.2;
    
    std::cout << std::format("{:0.63f}\n", d);
}
Goidelic answered 30/9, 2023 at 1:46 Comment(0)
W
-2

Well there are good math libraries in math.h

Also storing your figures in floats, doubles or long doubles will allow for more precise operations.

Floats offer 7 significant digits while doubles offer 16 significant digits.

source

Also when printing out usually people use _snprintf or printf and you can format those doubles, floats to the precision you want like:

Float Precision

printf("Value %8.2f", floatVariable);

This says you require a total field of 8 characters, within the 8 characters the last 2 will hold the decimal part.

_snprintf(buffer, sizeof(buffer), "Value %.2f", floatVariable);

The example above requests the minimum field width and the last two characters are to hold the decimal part.

Westsouthwest answered 5/1, 2011 at 18:3 Comment(1)
Those are “digits after the decimal point”, not significant figures. For scientists and engineers there’s a very important difference between the two.Drawstring

© 2022 - 2024 — McMap. All rights reserved.