Tamanhos de ponto flutuante e problemas com arquiteturas x86 e máquinas 32 bits

Página Inicial / ∣V∣+∣E∣ (Gráfico) / Tamanhos de ponto flutuante e problemas com arquiteturas x86 e máquinas 32 bits
Processadores x86 tem um set de instruções chamado x87 que usa precisão interna de ponto de flutuante de 80 bits, enquanto que o double é de 64 bits. Isso gera problemas ao salvar e recuperar valores salvos na memória. Observe o exemplo:
#include <bits/stdc++.h>
using namespace std;

int main() {
    double br = 0;
    for (int i = 0; i < 2; i++) {
        double T, D;
        cin >> T >> D;
        double r = D/T;
        if (r > br) {
            cout << (i+1) << "\n";
            cerr << "saved " << br << " " << (*reinterpret_cast<uint64_t*>(&br)) << "\n";
            cerr << "now " << r << " " << (*reinterpret_cast<uint64_t*>(&r)) << "\n";
            br = r;
        }
    }
}
Com a entrada:
44 80
22 40
Se compilarmos com o flag -m32 e -O, obtemos a seguinte resposta:
1
saved 0 0
now 1.81818 4610867182131502359
2
saved 1.81818 4610867182131502359
now 1.81818 4610867182131502359
Que é extremamente estranha. Se salvamos o valor 1.81818 na memória, ele não pode ser igual ao que calculamos! Isso é devido à otimização: r é calculado usando a precisão de 80 bits, o que resulta em um valor um pouco diferente do br já guardado. Se compilarmos sem o flag -m32, mas com o flag -O em uma máquina 64 bits, obtemos a resposta correta:
1
saved 0 0
now 1.81818 4610867182131502359
      
Isto porque desta vez, usamos operações SSE que operam em 64 bits que estão ativadas por padrão quando compilamos em 64 bits.

Isso é importante lembrar porque o Codeforces e muitos judges usam máquinas 32 bits por padrão. Temos algumas opções para arrumar este erro: