Следующий код:
#include <iostream>
#include <ios>
int main() {
auto mod = 1e9+7;
std::cout << mod << '\n';
std::cout << std::fixed << mod << '\n';
}
выходы:
1e+009
1000000007.000000
Я думаю, что в данном случае mod
— это число с плавающей запятой, поэтому сначала на выходе выдается 1e+009, что может быть связано с точностью с плавающей запятой. Но почему после использования std::fixed
результат не равен 1000000000.000000 ?
Я заглянул в свой хрустальный шар, и он сказал мне, что вы скоро собираетесь решать задачу конкурентного программирования, и для этого вам необходимо дать результат по модулю 1000000007. Избегайте для этого операций с плавающей запятой, это доставит вам гораздо больше проблем, чем просто печать результата забавным способом.
Любая «задача», требующая результата по модулю 1000000007, не предполагает вычисления результата, а затем выполнения по модулю. Вместо этого вам следует сначала выполнить математические расчеты и посмотреть, как результат можно вычислить напрямую. Так что это математическая задача, а не обучение программированию.
Этот вопрос похож на: Не работает ли математика с плавающей запятой?. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.
Этот using namespace std; #define mod 1e9+7
вместе с предыдущими комментариями, похоже, указывает на то, что вы изучаете C++ не из хорошего источника. (Где вы изучаете C++?). Не используйте using namespace std;
, а если вам нужно постоянное использование static constexpr double mod = 1.0e9+7;
Но сначала узнайте об ограничениях вычислений с плавающей запятой, это беззаботное, но познавательное видео Числа с плавающей запятой (Том Скотт-Numberphile)
@RichardCritten Этот вопрос совсем другой. Это не имеет ничего общего с точностью операций с плавающей запятой. Речь идет о количестве значащих цифр по умолчанию, которое печатает cout.
Значение, хранящееся в mod
, равно 10000007.00
. Просто когда вы печатаете это значение без каких-либо флагов формата, среда выполнения может напечатать его с точностью по умолчанию, которая может не соответствовать вашим ожиданиям. Попробуйте добавить в свою программу оператор printf("%f\n", mod);
— вы увидите, что printf по умолчанию форматирует значения с плавающей запятой по-другому.
Я думаю, это хороший вопрос (+1). Если вы считаете это плохим, потому что ответ очевиден, подумайте еще раз. Если вас обидела константа 1000000007, постарайтесь быть более разумными! Обычно мы здесь не объясняем –1, но если вы считаете, что это оправдано, объясните.
«из-за точности с плавающей запятой». Это слишком краткое объяснение, поскольку предполагается, что вы знаете, что происходит (но вы этого не знаете, о чем свидетельствует этот вопрос). Перейдите на более глубокий уровень объяснения, что-то на уровне «насколько я понимаю, точность литерала с плавающей запятой не превышает девяти десятичных цифр [предоставьте ссылку, если таковая имеется], поэтому 7
в десятом месте опускается» . Я бы также посоветовал прочитать Как спросить; этот вопрос был бы лучше, если бы у него был более конкретный заголовок и если бы он объяснял сценарий в тексте перед публикацией какого-либо кода.
«(Все необходимые файлы заголовков включены через #include<bits/stdc++.h>)» — было ли проще написать это, чем начинать код с #include <bits/stdc++.h>
, и в целом меньше печатать (и было ли проще копировать и компилировать -запустите свой код)? (Хотя было бы еще лучше, если бы вы использовали стандартный #include <iostream>
.)
Главной особенностью этого вопроса, по-видимому, является предположение о том, что double
не может точно представлять 1000000007
. Без этого предположения этот вопрос соответствовал бы нескольким другим, например Точность числа double в этом коде составляет всего 6 цифр - Как отобразить больше десятичных знаков в выходной консоли? - Как мне напечатать двойное значение с полной точностью, используя cout? Я не уверен, следует ли считать их дубликатами, учитывая отправную точку этого вопроса.
1. Вам следует избегать использования макросов, если в этом нет крайней необходимости. 2. Вы не должны/не можете включать <bits/stdc++.h>
— это обычно недоступно. 3. Вам следует избегать using namespace std
. Все это изменил.
@Evg: Поскольку этот момент не имеет значения для вопроса, который сам по себе является правильным вопросом, я считаю, что лучше комментировать и исправлять (что я и сделал), а не просто комментировать.
1e9 + 7
Это число точно представимо в double
, здесь нет потери точности.
Однако, когда вы печатаете его с помощью std::cout << mod
, он печатается с точностью по умолчанию, которая составляет 6 десятичных цифр. Поэтому 7 не печатается.
Вы можете настроить точность std::cout
с помощью std::setprecision
манипулятора:
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::setprecision(10) << mod << '\n';
}
распечатаю 1000000007
Я заметил одну вещь: первоначальный вывод вопроса (1e+009
) представлен в научной записи. Не могли бы вы сохранить этот формат в своем ответе, только с повышенной точностью? (Это может быть дополнение к демонстрации эффекта std::setprecision(10)
самого по себе.)
На самом деле не гарантируется, что 1e9+7
представимо в double
. Это верно для конкретных представлений с плавающей запятой (например, IEEE), но не для других. Стандарт C++ не требует использования IEEE с плавающей запятой, и существуют реальные реализации, которые не используют IEEE.
@Питер: 1 000 000 007 точно можно представить в double
. C++ наследует некоторые минимальные требования к типам с плавающей запятой из C посредством различных ссылок (2 Нормативные ссылки [intro.refs] 1: «Следующие документы упоминаются в тексте таким образом, что часть или все их содержимое представляет собой требования этот документ…»), а требуемая точность C достаточна, чтобы гарантировать представимость 1 000 000 007.
@IlyaPopov Спасибо за это, не могли бы вы подтвердить, дает ли фиксированное больше, чем просто удаление научных обозначений здесь (я новичок в кодировании и не смог найти ни одного онлайн-ресурса, который мог бы разъяснить использование слова «исправленное»)
@Lunatica Вставка std::fixed
в выходной поток просто изменяет форматирование по умолчанию для этого потока, то есть способ отображения чисел с плавающей запятой в потоке. Это не вносит никаких изменений в сами числа с плавающей запятой.
@Lunatica См. en.cppreference.com/w/cpp/io/manip/fixed
Почему вы ожидали такого результата?