可以檢查通過浮點類型檢查宏恆定FLT_RADIX
的值的表示所用的鹼(在報頭<cfloat>
定義)。正如你可能已經知道的那樣,二進制系統被大多數現代計算機內部使用,而不是十進制。
現在考慮一個像1/3的有理數。它不能用基數爲10的有限數字表示,最終會出現一些近似值,如0.3333333和可接受的錯誤。請注意,相同的數字可以用有限數量的數字(0.1)在基本3系統中表示。
您嘗試打印的數字9/450具有「好」的基數10表示,0.02,但它不能以絕對精度表示在基數2中,即使可以在不添加分割的情況下執行分割任何錯誤。不要誤以爲'2',考慮0.02 = 2/100 = 1/50 = 1 /(2 * 5 ),其中1/5只能近似於基數2.
無論如何,有辦法實現你想要的,例如使用輸出操縱器std::setprecision
和std::fixed
(在標頭<iomanip>
中定義),或者甚至編寫(非常醜陋的)自定義函數。看看該程序的輸出:
#include <iostream>
#include <cmath>
#include <iomanip>
#include <vector>
#include <cstdint>
// splits a number into its integral and fractional (a vector of digits) parts
std::vector<uint8_t> to_digits (
long double x, uint8_t precision, long double &integral
);
// Reconstructs the approximated number
long double from_digits (
long double integral_part, std::vector<uint8_t> &fractional_part
);
int main()
{
using std::cout;
int n = 9, m = 450;
long double S;
S = static_cast<long double>(n)/m;
cout << "\nBase 10 representation of calculated value:\n"
<< std::setprecision(70) << S << '\n';
// This ^^^^^^^^^^^^^^^^^^^^^ will change only how the value is
// printed, not its internal binary representation
cout << "\nBase 10 representation of literal:\n"
<< 0.02L << '\n';
// This ^^^^^ will print the exact same digits
// the next greater representable value is a worse approximation
cout << "\nNext representable value:\n"
<< std::nextafter(S, 1.0) << '\n';
// but you can try to obtain a "better" output
cout << "\nRounded representation printed using <iomanip> functions:\n"
<< std::setprecision(20) << std::fixed << S << '\n';
cout << "\nRounded fractional part printed using custom function:\n";
long double integral_part;
auto dd = to_digits(S, 20, integral_part);
for (auto const d : dd)
{
cout << static_cast<int>(d);
}
cout << '\n';
// Reversing the process...
cout << "\nApproximated value (using custom function):\n";
auto X = from_digits(integral_part, dd);
cout << std::setprecision(70) << std::fixed << X << '\n';
cout << std::setprecision(20) << std::fixed << X << '\n';
}
std::vector<uint8_t> to_digits (
long double x, uint8_t precision, long double &integral
)
{
std::vector<uint8_t> digits;
long double fractional = std::modf(x, &integral);
for (uint8_t i = 0; i < precision; ++i)
{
long double digit;
fractional = std::modf(fractional * 10, &digit);
digits.push_back(digit);
}
if (digits.size() && std::round(fractional) == 1.0L)
{
uint8_t i = digits.size();
while (i)
{
--i;
if (digits[i] < 9)
{
++digits[i];
break;
}
digits[i] = 0;
if (i == 0)
{
integral += 1.0L;
break;
}
}
}
return digits;
}
long double from_digits (
long double integral_part, std::vector<uint8_t> &fractional_part
)
{
long double x = 1.0L;
for (auto d : fractional_part)
{
x *= 10.0L;
integral_part += d/x;
}
return integral_part;
}
這看起來像它可能的副本[?是浮點運算破(https://stackoverflow.com/questions/588004/is-floating-point儘管我承認我並不完全確定代碼中發生了什麼事情。 – Carcigenicate
我試圖讓一個程序從兩個數字的分割中得到20位小數。 –