1

Здравствуйте, решаю задачку для олимпиады.

Написал код, но выдаёт что не верный результат, думаю проблема в типе данных.(Проверять размерность данных и т.п. через if и так далее - не нужно)

#include <iostream>
#include <math.h>

using namespace std;

int main()
{
    double a,b,c, S, P,p, R;
    cin >> a;
    cin >> b;
    cin >> c;

    P = a + b + c;
    p = P / 2;
    S = sqrt(p*(p - a)*(p - b)*(p - c));
    R = sqrt(((p - a)*(p - b)*(p - c)) / p);

    cout << P << " "<<S<<" "<<R;

    return 0;
}
  • Ну и? Где пример входа, на котором выдается "не верный результат"? Где сам "не верный результат"? – AnT stands with Russia Jul 11 '17 at 09:37
  • @AnT, да всё там ясно. – Qwertiy Jul 11 '17 at 09:39
  • @AnT, Там не показывает какие вводные данные используют, ты просто загружаешь код и машина сверяет результат твоей программы со своими забитыми значениями. – Пионер Jul 11 '17 at 09:39
  • "double numbers" - числа двойной точности, а не двойных числа. Ну и я бы вообще перевёл как "дробных". – Qwertiy Jul 11 '17 at 09:40

1 Answers1

2

Не стоит использовать формулу Герона для подсчёта площади - она приводит к переполнению или очень большой погрешности. Тебе гарантировали, что площадь не превосходит 9223372036854775807, но ты-то считаешь квадрат этого числа.

Если ничего не путаю, стоит воспользоваться теоремой синусов или косинусов.

Кроме того, надо использовать тип long double (или более точный) для всех данных и компилятор gcc (не Visual Studio). Число, указанное в качестве ограничения, это 263-1. У обычного double есть только 53 значащих бита, чего не хватит даже для точного считывания входных данных.

Qwertiy
  • 123,725
  • Вполне может быть, что все не так экстремально, а проблема лишь в том, что умолчательный формат округляет результат всего до, скажем, 6 знаков после запятой, а по условию требуется 8. Если бы во входе наличествовали большие значения, то было бы странно формулировать требование точности в терминах абсолютной погрешности. – AnT stands with Russia Jul 11 '17 at 09:47
  • @AnT, я точно помню, что про формулу Герона говорили, что её не надо использовать из-за переполнений. Есть формулы получше. – Qwertiy Jul 11 '17 at 09:48
  • Через радиус вписанной окружности попробую – Пионер Jul 11 '17 at 09:49
  • @Пионер, а вообще, спецификатор вывода на 10 знаков действительно стоит поставить явно. – Qwertiy Jul 11 '17 at 09:49
  • @Qwertiy: Может быть и есть и получше. Но я не вижу смысла огород городить, если дело не в этом. Еще раз: формулировка требуемой точности в терминах абсолютной погрешности намекает на то, что входные данные будут относительно небольшими числами. – AnT stands with Russia Jul 11 '17 at 09:50
  • @AnT, какие ещё намекают, если в условии прямым текстом сказано "Входные данные гарантируют, что входы и результаты будут меньше 9223372036854775807,0" – Qwertiy Jul 11 '17 at 09:52
  • @Пионер, надо использовать long double и компилятор gcc. Потому что в double 9223372036854775807 = 9223372036854776000. – Qwertiy Jul 11 '17 at 09:53
  • Для "экстремально-тупоугольного" треугольника формула Герона вообще посчитает не площадь, а нечто невразумительное... – Akina Jul 11 '17 at 09:55
  • @Qwertiy Это замечательно, но если входные данные будут приближаться к таким значениям, то обеспечить требуемую в условии абсолютную погрешность результата 1e-8 в рамках типа double будет невозможно, независимо от того, каким способом вычисления вы пользуетесь. И я почти уверен, что это задача не на использование библиотек поддержки чисел бесконечной точности. – AnT stands with Russia Jul 11 '17 at 09:57
  • 1
    @AnT, да что ж за число такое? Почему на Си++ получается 9223372036854775808 (ideone и codepad), на js 9223372036854776000 (jsfiddle), а на C# 9223372036854780000 (ideone)? – Qwertiy Jul 11 '17 at 10:06
  • @Qwertiy, я отсылаю лишь код, дело не в IDE. – Пионер Jul 11 '17 at 10:10
  • @Пионер, ты указываешь компилятор. VS не поддерживает long double и использует вместо него обычный 8-байтный double. Смени компилятор на gcc. – Qwertiy Jul 11 '17 at 10:12
  • Не сработало, теже результаты. – Пионер Jul 11 '17 at 12:05
  • @Пионер, тогда бери джаву и BigDecimal. – Qwertiy Jul 11 '17 at 12:21
  • @Qwertiy, там на С++ надо. – Пионер Jul 11 '17 at 15:59
  • @Пионер, а считывание тоже logn double сделал? Попробуй потестить на прямоугольном треугольнике 9223372036854775807 1 9223372036854775807. Ответ 4611686018427387903.5. – Qwertiy Jul 12 '17 at 17:51
  • https://ru.stackoverflow.com/q/690856/178988 – Qwertiy Jul 12 '17 at 17:52
  • @Qwertiy ответ: 1.84467e+19 0 0 Все переменные long double, вдобавок везде понатыкал типизацию (long double) – Пионер Jul 12 '17 at 18:22
  • @Пионер, что ещё за e+19? Надо выводить число точно. И что ещё за 0 0 вообще? Это же неверно. И хм.. я перестарался - не учёл ограничение на периметр. Попробуй в 2 раза меньше. – Qwertiy Jul 12 '17 at 19:02
  • @Qwertiy Нашел проблему. Всё дело в cout. Он не правильно выводил информацию(те ешки), переделал под printf - всё заработало! – Пионер Jul 12 '17 at 20:54