简体   繁体   中英

Could we use strings for high precision floating-point numbers?

I am currently programming a software which needs high precision floating-point numbers. Sometimes I need more precision than a double can give me. I know why classic floating-point numbers can only achieve a limited amount of precision.

I was thinking about this problem and had the idea to use string to represent numbers and do calculation with them.

string number_one = "12.3459233547343432";
string number_two = "738.67632487523747384";

string sum = sum_strings(number_one, number_two);

cout << sum << endl; // 751.0222482299717...

The function sum_strings would then perform the addition like we have all learned it in primary school (just with floating-point):

在此处输入图片说明

Substraction would work the same way. Multiplication and division would be more complicated but it would also work.

I think theoretically you could achieve as much precision as you need (with enough RAM to store the strings).

My questions are:

  1. Would this technique be much slower (for ~10 fractional digits)?
  2. Is it used already and are there libraries implementing it?

This would be quite a bit slower, since you'd be using a full char for a single digit of data, and operations you performed would be totally unable to use hardware-implemented arithmetic operations. A much better way would be to design an arbitrary-length binary format instead. See https://gmplib.org . There are many other options as well.

You're on the right track, but std::string is not the right data structure. Instead, use std::vector<unsigned char> , with each element of the vector holding a value in the range 0 to std::numeric_limits<unsigned char>::max() . That upper limit is typically 255. The rules for addition and subtraction are just like the ones you learned as a kid, except that you have 256 fingers instead of 10. That sounds flippant, but the idea is that you have a bunch of digits for a base-256 representation of a number, and the rules for adding and subtracting work the same, except that you carry when the result is greater than 255, not when it's greater than 9. That's easier than it sounds; just do the arithmetic with a larger unsigned type; the result % 256 is the value in the current digit, and the result / 256 is the amount to carry.

Once you've wrapped your thoughts around that, you could also consider using std::vector<unsigned long long> instead of std::vector<unsigned char> , which would mean doing arithmetic in base-2^64.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM