我怎样才能在 C++ 中用 N 个小数字符串化一个分数
How can I stringify a fraction with N decimals in C++
我想在 C++ 中以可变精度对一部分无符号整数进行字符串化。因此 1/3
将使用 2
的 precision
打印为 0.33
。我知道 float
和 std::ostream::precision
可用于快速而肮脏的解决方案:
std::string stringifyFraction(unsigned numerator,
unsigned denominator,
unsigned precision)
{
std::stringstream output;
output.precision(precision);
output << static_cast<float>(numerator) / denominator;
return output.str();
}
然而,这还不够好,因为 float
精度有限,实际上无法准确表示十进制数。我还有哪些其他选择?如果我想要 100 位左右的数字,或者在循环分数的情况下,即使 double
也会失败。
总是可以只执行长除法来字符串化digit-by-digit。请注意,结果由整数部分和小数部分组成。我们可以通过简单地使用 /
运算符进行除法并调用 std::to_string
来获得整数部分。对于其余部分,我们需要以下功能:
#include <string>
std::string stringifyFraction(const unsigned num,
const unsigned den,
const unsigned precision)
{
constexpr unsigned base = 10;
// prevent division by zero if necessary
if (den == 0) {
return "inf";
}
// integral part can be computed using regular division
std::string result = std::to_string(num / den);
// perform first step of long division
// also cancel early if there is no fractional part
unsigned tmp = num % den;
if (tmp == 0 || precision == 0) {
return result;
}
// reserve characters to avoid unnecessary re-allocation
result.reserve(result.size() + precision + 1);
// fractional part can be computed using long divison
result += '.';
for (size_t i = 0; i < precision; ++i) {
tmp *= base;
char nextDigit = '0' + static_cast<char>(tmp / den);
result.push_back(nextDigit);
tmp %= den;
}
return result;
}
您可以轻松地将其扩展为与其他基础一起使用,只需将 base
设为模板参数即可,但您不能再只使用 std::to_string
。
我想在 C++ 中以可变精度对一部分无符号整数进行字符串化。因此 1/3
将使用 2
的 precision
打印为 0.33
。我知道 float
和 std::ostream::precision
可用于快速而肮脏的解决方案:
std::string stringifyFraction(unsigned numerator,
unsigned denominator,
unsigned precision)
{
std::stringstream output;
output.precision(precision);
output << static_cast<float>(numerator) / denominator;
return output.str();
}
然而,这还不够好,因为 float
精度有限,实际上无法准确表示十进制数。我还有哪些其他选择?如果我想要 100 位左右的数字,或者在循环分数的情况下,即使 double
也会失败。
总是可以只执行长除法来字符串化digit-by-digit。请注意,结果由整数部分和小数部分组成。我们可以通过简单地使用 /
运算符进行除法并调用 std::to_string
来获得整数部分。对于其余部分,我们需要以下功能:
#include <string>
std::string stringifyFraction(const unsigned num,
const unsigned den,
const unsigned precision)
{
constexpr unsigned base = 10;
// prevent division by zero if necessary
if (den == 0) {
return "inf";
}
// integral part can be computed using regular division
std::string result = std::to_string(num / den);
// perform first step of long division
// also cancel early if there is no fractional part
unsigned tmp = num % den;
if (tmp == 0 || precision == 0) {
return result;
}
// reserve characters to avoid unnecessary re-allocation
result.reserve(result.size() + precision + 1);
// fractional part can be computed using long divison
result += '.';
for (size_t i = 0; i < precision; ++i) {
tmp *= base;
char nextDigit = '0' + static_cast<char>(tmp / den);
result.push_back(nextDigit);
tmp %= den;
}
return result;
}
您可以轻松地将其扩展为与其他基础一起使用,只需将 base
设为模板参数即可,但您不能再只使用 std::to_string
。