Определение
Основной тип для хранения нецелых чисел, потому что !Float говно, даже разработчики языка это понимали и при выводе с помощью cout !Float числа переводятся в double, они даже отдельный перегруз для него не сделали, сразу видны приоритеты. Про double мало что можно сказать, кроме того, что он неточный, из-за того, что хранятся такие числа с помощью двоичной системы и выходит не очень точно. Аналогично long long в памяти double занимает 64 бит, хранятся нецелые числа в нем так: 1 !Бит уходит под знак, 11 следующих !Бит уходит на экспоненту, а все оставшиеся 52 на мантиссу и это не настолько точно, как хотелось бы. Итоговая формула выглядит так: Где Z - знак числа, M - мантисса, E - экспонента. Из-за такой системы маленькие числа хранятся довольно точно, ведь нам не нужно делать большую экспоненту, которая при умножении портит точность, а вот большие числа начинают страдать. Решением этой проблемы может стать кастомный тип, которые отдельно содержит целую и дробную части числа и чуть точнее перемножает их, но обычно таким не стоит заморачиваться, ведь такая точность редко становится нужна. С double нужно быть аккуратными при выводе, ведь стандартный вывод больших чисел в нем реализован через e, и это нужно исправлять с помощью setprecision. В среднем double поддерживает 16 знаков, но как я уже писал выше, точность зависит от размера числа. Если вам не хватает даже такой точности, то первое, что вам стоит сделать, это перейти на !Long double, и только потом искать другие решения проблемы.
Примеры
Double справился с очевидным деление, с которым не справился float.
#include <bits/stdc++.h>
using namespace std;
int main() {
double x = double(92) / double(10); // Предполагаемое число 9.2
cout << setprecision(10) << x; // Выводимое число - 9.2
}
Но на больших числа происходят неточности:
#include <bits/stdc++.h>
using namespace std;
int main() {
double x = double(99999999999) / double(1000); // Предполагаемое число 99999999.999
cout << fixed
<< setprecision(10) << x; // Выводимое число - 99999999.998999998
}