C++ significant figures

2020-06-16 02:11发布

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!

7条回答
家丑人穷心不美
2楼-- · 2020-06-16 02:22

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.

查看更多
贪生不怕死
3楼-- · 2020-06-16 02:28

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.

查看更多
贼婆χ
4楼-- · 2020-06-16 02:29

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.

查看更多
狗以群分
5楼-- · 2020-06-16 02:29

You can also:

#define SIGNIFICANT_DIGITS 3
const float SIGNIFICANT_DIGITS_PWR = powf(10.0f, SIGNIFICANT_DIGITS);

float f;
std::cin >> f;

int int_digits = (int)log10f(f) + 1;
if (int_digits > 1) {
    float prod = SIGNIFICANT_DIGITS_PWR / powf(10.0f, int_digits);
    f = (float)(int)(f * prod) / prod;
} else {
    f = (float)((int)(f * SIGNIFICANT_DIGITS_PWR)) / SIGNIFICANT_DIGITS_PWR;
};

std::cout << f << '\n';

Output:

0.1234
> 0.123
12.34
> 12.3
1234
> 1230
查看更多
beautiful°
6楼-- · 2020-06-16 02:35

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;
查看更多
贪生不怕死
7楼-- · 2020-06-16 02:42

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.

查看更多
登录 后发表回答