Как работает функция ceil в С++?

Когда я выполняю этот код, значение ans1, ans2 равно 50002896 и 50005000. Я знаю, что есть некоторые проблемы с функцией ceil, но не смог выяснить точную причину.

#include <bits/stdc++.h>
using namespace std;
int main()
{
      long long ans1 = 0, ans2 = 0;

      for (long long i = 1; i <= 10000; i++)
      {
            ans1 = ans1 + ceil((float)i / 1);
            ans2 = ans2 + i;
      }
      cout << ans1 << " " << ans2 << endl;
}
#include <bits/stdc++.h> -- Включите правильные файлы заголовков, а не этот.
PaulMcKenzie 20.11.2022 07:29

Наверное, это из-за (float), а не из-за ceil. float не совсем точно.

user253751 20.11.2022 07:33

Не используя надлежащие стандартные заголовочные файлы, а также используя using namespace std;, не зная, что извлекает этот нестандартный заголовочный файл, мы не знаем, является ли он std::ceil или ceil из библиотеки времени выполнения C. Вот почему использование bits...whatever — плохая идея, не говоря уже о том, что это нестандартно.

PaulMcKenzie 20.11.2022 07:37

@PaulMcKenzie Без заголовка cmath компиляция завершается с ошибкой с флагами c++11, c++14, c++17 и c++20: ошибка: «ceil» не является членом «std» — я не уверен, чем отличаются ceil() и std::ceil().

Rohan Bari 20.11.2022 07:45

@RohanBari Нет гарантии компиляции, если вы не включите правильные заголовочные файлы.

PaulMcKenzie 20.11.2022 07:47

@PaulMcKenzie Примечание: использование ceil(без std::) также может привести к разным результатам в зависимости от импорта <cmath> или <math.h>

Ranoiaetep 20.11.2022 08:17

@Ranoiaetep - Да, поэтому использование нестандартного заголовка «включить все» проблематично.

PaulMcKenzie 20.11.2022 08:32

@Chinnmay B S Почему float используется ceil((float)i / 1) вместо double или long double?

chux - Reinstate Monica 20.11.2022 08:34

Кроме того, вместо использования ceil((some_float / 1)) для преобразования числа с плавающей запятой в целое число используйте вместо этого std::lround и std::llround.

Ranoiaetep 20.11.2022 08:48
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
2
11
144
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Еще немного информации о представлении с плавающей запятой: Википедия IEEE 754 . И связанный пост: Какое первое целое число, которое число с плавающей запятой IEEE 754 не может точно представить?.

Следующий код является минимальной демонстрацией той же проблемы, которая вызывает вашу проблему:

float f1 = 100000000;
f1++;
std::cout << std::to_string(f1) << std::endl;

[Неверно] Вывод (ожидаемый: +1):

100000000.000000

Один из подходов — использовать double вместо float. Это не решит основную проблему, но значительно увеличит диапазон представляемых целых чисел:

double f1 = 100000000;
f1++;
std::cout << std::to_string(f1) << std::endl;

Вывод:

100000001.000000

Некоторые примечания:

  1. лучше избегать #include <bits/stdc++.h> - см. здесь: Почему я не должен #include <bits/stdc++.h>?.
  2. лучше избегать using namespace std - см. здесь Почему "using namespace std;" считается плохой практикой?.

Во-первых, попробуйте использовать определенные заголовки, такие как #include , в этом случае .because #include <bits/stdc++.h> принесет много мусора.

Итак, проблема с float, а не с ceil, описанная ниже

Значения с плавающей запятой не представляют точные значения.

Код:-

#include <iostream>
#include <iomanip>
using namespace std;

// Driver Code
int main()
{
    float num1 = 10000.29;
    float num2 = 10000.2;

    // Output should be 0.0900000000
    cout << std::setprecision(15)
        << (num1 - num2);
    return 0;
}

Вывод :-

0.08984375

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