2017-01-28 1 views
-1

У меня есть эта линия в моем коде (LL долго долго ИНТ):Получение исключительной ситуации с плавающей: 8

ll d = (x/((y/1000000) - 1)); 

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

ll d = (1000000*x)/(y-1000000); 

ошибка исчезает. Простая алгебра заставит вас поверить, что они оба - одно и то же.

Вот полный код, который предназначен для проблемы UVa 10660, Grocery Store. https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=643&page=show_problem&problem=2177

//Problem Link: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=643&page=show_problem&problem=2177 
//Problem type: Complete Search 

#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <climits> 
#include <stdio.h> 
#include <queue> 
#include <set> 
#include <cmath> 
#include <assert.h> 
#include <bitset> 
#include <map> 
#include <unordered_map> 
#include <iomanip> //cout << setprecision(n) << fixed << num 

typedef long long int ll; 
using namespace std; 

int main() { 
    //freopen("output.out", "w", stdout); 
    int cnt = 0; 
    for (int a = 1; a*4 <= 2000; a++) { 
     for (int b = a; a+3*b <= 2000; b++) { 
      for (int c = b; a+b+2*c <= 2000; c++) { 
       ll x = a+b+c; 
       ll y = a*b*c; 
       if (y <= 1000000) continue; 
       //ll d = (x/((y/1000000) - 1)); 
       ll d = (1000000*x)/(y-1000000); 
       if (d < c || x + d > 2000) continue; 
       if (abs((x + d)/100.0 - (y * d)/100000000.0) < 1e-8) { 
        cout << setprecision(2) << fixed << a/100.0 << " " << b/100.0 << " " << c/100.0 << " " << d/100.0 << endl; 
        cnt++; 
       } 
      } 
     } 
    } 
    cout << cnt << endl; 
    return 0; 
} 

Если изменить его ll d = (x/((y/1000000.0f) - 1)) однако, то ошибка исчезает, но я получаю неправильный ответ, и количество строк в выводе только 717, в то время как она должна быть 949 (я должен был Google ответ, чтобы выяснить этот странный вопрос: /)

+0

Вы получаете SIGFPE из-за целого деления на ноль. – kennytm

+0

Я не думаю, что это возможно. "if (y <= 1000000) продолжать;" y никогда не равно 1000000, поэтому не должно быть деления на ноль. – SinByCos

+0

'(x/((y/1000000) - 1))' может вызывать деление на ноль до тех пор, пока 'y/1000000 == 1'. – kennytm

ответ

1

Во-первых, здесь нет арифметики с плавающей запятой: все делается целыми числами (в частности, long long int).

Это означает, что, когда y между 1000000 и 1999999 включительно, результат деления y/1000000 будет 1. Следовательно, вычитание из него 1 приведет к нулю знаменателю и делению на нулевое исключение.

Ваше второе выражение даст тот же результат, только если y равно 1000000, но программа будет аварийно завершена с тем же исключением.

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

+0

Hah! Имеет смысл. :) спасибо – SinByCos

+0

Но почему я получаю WA с ll d = (x/((y/1000000.0f) - 1)); ? – SinByCos

+1

@SinByCos Потому что вы попадаете в числа с плавающей запятой, смешанные с 'long long'. У них разные диапазоны. 'double' имеют только 52 бит точности, но гораздо более высокий диапазон, в то время как 'long long' имеют точность 63 бит и более узкий диапазон. Смешанная математика вблизи граничных случаев дает результаты, которые могут быть сильно удалены от цели. – dasblinkenlight

Смежные вопросы