Неожиданный результат при выводе с плавающей запятой

Следующий код:

#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 ?

Почему вы ожидали такого результата?

HolyBlackCat 04.07.2024 19:44

Я заглянул в свой хрустальный шар, и он сказал мне, что вы скоро собираетесь решать задачу конкурентного программирования, и для этого вам необходимо дать результат по модулю 1000000007. Избегайте для этого операций с плавающей запятой, это доставит вам гораздо больше проблем, чем просто печать результата забавным способом.

user555045 04.07.2024 19:47

Любая «задача», требующая результата по модулю 1000000007, не предполагает вычисления результата, а затем выполнения по модулю. Вместо этого вам следует сначала выполнить математические расчеты и посмотреть, как результат можно вычислить напрямую. Так что это математическая задача, а не обучение программированию.

BoP 04.07.2024 19:52

Этот вопрос похож на: Не работает ли математика с плавающей запятой?. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.

Richard Critten 04.07.2024 19:55

Этот using namespace std; #define mod 1e9+7 вместе с предыдущими комментариями, похоже, указывает на то, что вы изучаете C++ не из хорошего источника. (Где вы изучаете C++?). Не используйте using namespace std;, а если вам нужно постоянное использование static constexpr double mod = 1.0e9+7; Но сначала узнайте об ограничениях вычислений с плавающей запятой, это беззаботное, но познавательное видео Числа с плавающей запятой (Том Скотт-Numberphile)

Pepijn Kramer 04.07.2024 20:03

@RichardCritten Этот вопрос совсем другой. Это не имеет ничего общего с точностью операций с плавающей запятой. Речь идет о количестве значащих цифр по умолчанию, которое печатает cout.

Ilya Popov 04.07.2024 20:22

Значение, хранящееся в mod, равно 10000007.00. Просто когда вы печатаете это значение без каких-либо флагов формата, среда выполнения может напечатать его с точностью по умолчанию, которая может не соответствовать вашим ожиданиям. Попробуйте добавить в свою программу оператор printf("%f\n", mod); — вы увидите, что printf по умолчанию форматирует значения с плавающей запятой по-другому.

selbie 04.07.2024 20:24

Я думаю, это хороший вопрос (+1). Если вы считаете это плохим, потому что ответ очевиден, подумайте еще раз. Если вас обидела константа 1000000007, постарайтесь быть более разумными! Обычно мы здесь не объясняем –1, но если вы считаете, что это оправдано, объясните.

anatolyg 04.07.2024 20:51

«из-за точности с плавающей запятой». Это слишком краткое объяснение, поскольку предполагается, что вы знаете, что происходит (но вы этого не знаете, о чем свидетельствует этот вопрос). Перейдите на более глубокий уровень объяснения, что-то на уровне «насколько я понимаю, точность литерала с плавающей запятой не превышает девяти десятичных цифр [предоставьте ссылку, если таковая имеется], поэтому 7 в десятом месте опускается» . Я бы также посоветовал прочитать Как спросить; этот вопрос был бы лучше, если бы у него был более конкретный заголовок и если бы он объяснял сценарий в тексте перед публикацией какого-либо кода.

JaMiT 04.07.2024 22:35

«(Все необходимые файлы заголовков включены через #include<bits/stdc++.h>)» — было ли проще написать это, чем начинать код с #include <bits/stdc++.h>, и в целом меньше печатать (и было ли проще копировать и компилировать -запустите свой код)? (Хотя было бы еще лучше, если бы вы использовали стандартный #include <iostream>.)

JaMiT 04.07.2024 22:41

Главной особенностью этого вопроса, по-видимому, является предположение о том, что double не может точно представлять 1000000007. Без этого предположения этот вопрос соответствовал бы нескольким другим, например Точность числа double в этом коде составляет всего 6 цифр - Как отобразить больше десятичных знаков в выходной консоли? - Как мне напечатать двойное значение с полной точностью, используя cout? Я не уверен, следует ли считать их дубликатами, учитывая отправную точку этого вопроса.

JaMiT 04.07.2024 23:01

1. Вам следует избегать использования макросов, если в этом нет крайней необходимости. 2. Вы не должны/не можете включать <bits/stdc++.h> — это обычно недоступно. 3. Вам следует избегать using namespace std. Все это изменил.

einpoklum 06.07.2024 15:28

@Evg: Поскольку этот момент не имеет значения для вопроса, который сам по себе является правильным вопросом, я считаю, что лучше комментировать и исправлять (что я и сделал), а не просто комментировать.

einpoklum 06.07.2024 15:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
14
182
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
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) самого по себе.)

JaMiT 04.07.2024 22:48

На самом деле не гарантируется, что 1e9+7 представимо в double. Это верно для конкретных представлений с плавающей запятой (например, IEEE), но не для других. Стандарт C++ не требует использования IEEE с плавающей запятой, и существуют реальные реализации, которые не используют IEEE.

Peter 05.07.2024 03:36

@Питер: 1 000 000 007 точно можно представить в double. C++ наследует некоторые минимальные требования к типам с плавающей запятой из C посредством различных ссылок (2 Нормативные ссылки [intro.refs] 1: «Следующие документы упоминаются в тексте таким образом, что часть или все их содержимое представляет собой требования этот документ…»), а требуемая точность C достаточна, чтобы гарантировать представимость 1 000 000 007.

Eric Postpischil 06.07.2024 15:32

@IlyaPopov Спасибо за это, не могли бы вы подтвердить, дает ли фиксированное больше, чем просто удаление научных обозначений здесь (я новичок в кодировании и не смог найти ни одного онлайн-ресурса, который мог бы разъяснить использование слова «исправленное»)

Lunatica 06.07.2024 15:42

@Lunatica Вставка std::fixed в выходной поток просто изменяет форматирование по умолчанию для этого потока, то есть способ отображения чисел с плавающей запятой в потоке. Это не вносит никаких изменений в сами числа с плавающей запятой.

Steve Summit 06.07.2024 23:36

@Lunatica См. en.cppreference.com/w/cpp/io/manip/fixed

Steve Summit 07.07.2024 02:06

Другие вопросы по теме

Похожие вопросы

Тип RVV для члена класса в C++
Как передать значение A::a другому классу B::b, если в классе A у меня есть объект класса B
Как получить MAC-адрес моего локального сетевого интерфейса с помощью сокета Win или удаленного IP-адреса
Использование Open62541 для подключения к серверу не удалось из-за «Не найдено подходящего UserTokenPolicy для возможных конечных точек»
Информация о растровом изображении регулярно возвращает серию одних и тех же неправильных значений, прежде чем возвращать правильные цвета пикселей
Перемещение std::thread со ссылками
Как выбрать правильную перегрузку шаблона функции?
Ошибка EVP_DigestVerifyFinal — ECDSA P-256/SHA-256 с OpenSSL (Libcrypto)
Почему я получаю сообщение об ошибке «Ошибка анализа JSON: тип [json.Exception.type_error.302] должен быть массивом, но является объектом»
Переменная, условно объявленная constexpr в соответствии с выражением ее инициализации