Блог пользователя Zhur

Автор Zhur, 12 лет назад, По-русски

Всем привет!

После решения задачи решил поменять константы с double на float, но решение стало выдавать мусор, хотя, по идее, не должно было. На моей машине (g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2) всё работает как положено.

Посылки:

Возможно, это особенности здешнего компилятора GNU C++0x? Если да, то где можно посмотреть точную версию компилятора?

Спасибо!

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +8 Проголосовать: не нравится

При округлении к инту, не забывай добавлять эпсилон. (int)4.99999999997 округлится к четырём, а не к пяти. Single или Double Precision — значения не имеет.

http://codeforces.me/contest/82/submission/7011728

  • »
    »
    12 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится

    Спасибо, теперь понятно в чём дело.

    "При округлении к инту"

    Скорее, приведение к инту

    "Single или Double Precision — значения не имеет"

    Видимо, всё-таки имеет, если при double такое не случается?

    И ещё такой вопрос: почему в таком коде k получается равно 0, если на входе 5...

    #include <iostream>
    #include <cmath>
    
    using namespace std;
    
    int main()
    {
        int n;
    
        cin >> n;
    
        int k = log(n / 5.0f + 1.0f) / log(2.0f);
    
        cout << k << endl;
    }
    

    ... а в таком k равно 1?

        int n = 5;
    
        int k = log(n / 5.0f + 1.0f) / log(2.0f);
    
        cout << k << endl;
    

    Понятно, что это можно решить добавлением 1e-7, но всё-таки интересна причина :)

    Спасибо!

    • »
      »
      »
      12 лет назад, скрыть # ^ |
      ← Rev. 5  
      Проголосовать: нравится 0 Проголосовать: не нравится

      Да на самом деле не важно, приведение к инту или округление. Например, вместо round(x) тоже следует писать round(x + EPS), иначе 4.5 не обязательно округлится к пяти.

      По поводу последнего вопроса, я не знаток в этом, но почти наверняка связано с поведением оптимизатора (на сервере стоит флаг компиляции -O2).

      Под "не имеет значения, float или double" я имел ввиду, что такие операции, как деление и взятие логарифма неизбежно приведут к погрешностям. В какую сторону эти погрешности уведут полученное число, зависит исключительно от везения, а не от выбранного типа данных :)

      Прибавлять эпсилон при округлении, тем не менее, нужно не только после деления и взятия логарифма, а всегда, так как погрешность возникает ещё во многих разных случаях (большая разность между экспонентами слагаемых, данные представлены в двоичном виде и т.д.)