Другой подход заключается в округлении на основе двоичных цифр точности.Пример реализации ниже - не уверен, полезен ли он для вас, но, поскольку вы заставили меня играть, я подумал, что выложу его там.ч заголовок часто встречается на системах Linux: он может быть легко перенесен на Windows, но это, несомненно, немного повозка, запряженная волами и будет ли это уместно в любой производственный код вызова от случая к случаю 1007 * можно аппроксимировать некоторой десятичной.почти эквивалентны, например, умножьте требуемую десятичную точность на 10 и разделите на 3 (на основе 2 ^ 10 ~ = 10 ^ 3).
Входное число (10.1234 ...) с 1 битомточности 8;при 2 это 10 и т. д.
Отдельно, десятичное округление IMHO лучше всего делать во время вывода или при использовании представления с десятичной дробью (например, для хранения мантиссы int
и степени степени 10).
#include <ieee754.h>
#include <iostream>
#include <iomanip>
double round_double(double d, int precision)
{
ieee754_double* p = reinterpret_cast<ieee754_double*>(&d);
std::cout << "mantissa 0:" << std::hex << p->ieee.mantissa0
<< ", 1:" << p->ieee.mantissa1 << '\n';
unsigned mask0 = precision < 20 ? 0x000FFFFF << (20 - precision) :
0x000FFFFF;
unsigned mask1 = precision < 20 ? 0 :
precision == 53 ? 0xFFFFFFFF :
0xFFFFFFFE << (32 + 20 - precision);
std::cout << "masks 0:" << mask0 << ", 1: " << mask1 << '\n';
p->ieee.mantissa0 &= mask0;
p->ieee.mantissa1 &= mask1;
std::cout << "mantissa' 0:" << p->ieee.mantissa0
<< ", 1:" << p->ieee.mantissa1 << '\n';
return d;
}
int main()
{
double num = 10.123456789987654321;
for (int prec = 1; prec <= 53; ++prec)
std::cout << std::setiosflags(std::ios::showpoint | std::ios::fixed)
<< std::setprecision(60)
<< "round_double(" << num << ", " << prec << ") = "
<< round_double(num, prec) << std::endl;
}
Вывод ...
mantissa 0:43f35, 1:ba76eea7
masks 0:fff80000, 1: 0
mantissa' 0:0, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 1) = 8.000000000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:fffc0000, 1: 0
mantissa' 0:40000, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 2) = 10.000000000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:fffe0000, 1: 0
mantissa' 0:40000, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 3) = 10.000000000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:ffff0000, 1: 0
mantissa' 0:40000, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 4) = 10.000000000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:ffff8000, 1: 0
mantissa' 0:40000, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 5) = 10.000000000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:ffffc000, 1: 0
mantissa' 0:40000, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 6) = 10.000000000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:ffffe000, 1: 0
mantissa' 0:42000, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 7) = 10.062500000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:fffff000, 1: 0
mantissa' 0:43000, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 8) = 10.093750000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:7ffff800, 1: 0
mantissa' 0:43800, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, 9) = 10.109375000000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:3ffffc00, 1: 0
mantissa' 0:43c00, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, a) = 10.117187500000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:1ffffe00, 1: 0
mantissa' 0:43e00, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, b) = 10.121093750000000000000000000000000000000000000000000000000000
mantissa 0:43f35, 1:ba76eea7
masks 0:fffff00, 1: 0
mantissa' 0:43f00, 1:0
round_double(10.123456789987654858009591407608240842819213867187500000000000, c) = 10.123046875000000000000000000000000000000000000000000000000000
etc....