AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78932341
Accepted
dspyz
dspyz
Asked: 2024-08-30 21:47:03 +0800 CST2024-08-30 21:47:03 +0800 CST 2024-08-30 21:47:03 +0800 CST

Por que 2x - x == x na precisão de ponto flutuante IEEE?

  • 772

Eu esperaria que isso só acontecesse quando o último bit da mantissa fosse 0. Caso contrário, para subtraí-los (já que seus expoentes diferem em 1), xperderia um pouco de precisão primeiro e o resultado acabaria sendo arredondado para cima ou para baixo.

Mas um experimento rápido mostra que isso parece sempre valer (assumindo que xe 2xsão finitos) para qualquer número aleatório (incluindo aqueles com um 1bit à direita).

import random
import struct
from collections import Counter


def float_to_bits(f: float) -> int:
    """
    Convert a double-precision floating-point number to a 64-bit integer.
    """
    # Pack the float into 8 bytes, then unpack as an unsigned 64-bit integer
    return struct.unpack(">Q", struct.pack(">d", f))[0]


def check_floating_point_precision(num_trials: int) -> float:
    true_count = 0
    false_count = 0
    bit_counts = Counter()

    for _ in range(num_trials):
        x = random.uniform(0, 1)
        if 2 * x - x == x:
            true_count += 1
        else:
            false_count += 1

        bits = float_to_bits(x)

        # Extract the last three bits of the mantissa
        last_three_bits = bits & 0b111
        bit_counts[last_three_bits] += 1

    return (bit_counts, true_count / num_trials)


num_trials = 1_000_000
(bit_counts, proportion_true) = check_floating_point_precision(num_trials)

print(f"The proportion of times 2x - x == x holds true: {proportion_true:.6f}")
print("Distribution of last three bits (mod 8):")
for bits_value in range(8):
    print(f"{bits_value:03b}: {bit_counts[bits_value]} occurrences")
The proportion of times 2x - x == x holds true: 1.000000
Distribution of last three bits (mod 8):
000: 312738 occurrences
001: 62542 occurrences
010: 125035 occurrences
011: 62219 occurrences
100: 187848 occurrences
101: 62054 occurrences
110: 125129 occurrences
111: 62435 occurrences
python
  • 3 3 respostas
  • 86 Views

3 respostas

  • Voted
  1. Sneftel
    2024-08-31T00:07:44+08:002024-08-31T00:07:44+08:00

    Quando você faz a aritmética manualmente, verá por que isso sempre vale. Sim, nas partes menos significativas você às vezes está fazendo xyz10 - wxyz1. Mas você também está subtraindo a parte mais significativa, então há espaço para a precisão total na parte inferior. Essa propriedade é conhecida como lema de Sterbenz . (Esse link fornece uma prova mais longa e formal.)

    • 4
  2. Best Answer
    Eric Postpischil
    2024-08-31T00:31:09+08:002024-08-31T00:31:09+08:00

    Se tivéssemos que fazer aritmética somente no formato de ponto flutuante, mesmo para valores internos durante a aritmética, então, sim, 2*x - xnem sempre produziria x. Por exemplo, com significandos de quatro bits, poderíamos ter:

    Expressão Valor/Cálculo
    x 1.001•2 0 (9)
    2*x 1.001•2 1 (18)
    2*x - x 1,001•2 1 − 1,001•2 0
    = 1,001•2 1 − 0,100•2 1 (operando deslocado para a direita e perdido um bit)
    = 0,101•2 1 = 1,010•2 0 (10).

    No entanto, não é assim que as implementações de ponto flutuante funcionam. Para obter os resultados corretos, elas usam mais dígitos internamente ou algoritmos mais sofisticados ou ambos. O IEEE-754 especifica que o resultado de uma operação elementar é o valor que você obteria ao calcular o resultado aritmético exato do número real sem erro ou arredondamento ou limitações em dígitos e, em seguida, arredondar esse número real para o valor mais próximo representável no formato de destino, usando a regra de arredondamento em vigor para a operação. (Mais comumente, essa regra de arredondamento é arredondar para o valor mais próximo, desempatando em favor daquele com um dígito baixo par em seu significando.)

    Uma consequência desse requisito é que, se o resultado matemático for representável no formato, o resultado computado deve ser esse resultado matemático. Quando o resultado matemático é representável, nunca há erro de arredondamento em uma operação elementar implementada corretamente.

    • 4
  3. no comment
    2024-08-31T04:21:17+08:002024-08-31T04:21:17+08:00

    Sejam x e y os valores reais representados pelos floats xe 2*x. Multiplicar por 2 é exato: a mantissa permanece a mesma, apenas o expoente aumenta em 1. Então y = 2x. Então você subtrai. A subtração de float nem sempre pode resultar na diferença real, pois isso pode não ser representável como float. Mas é especificado para dar o valor mais próximo que é representável como float (ou um mais próximo em caso de empate). E aqui, a diferença real é yx = 2x-x = x, e isso é representável como float, pois é com isso xque começamos.

    No seu outro caso 4*x - 3*x, multiplicar por 4 é novamente exato (o expoente simplesmente é aumentado em 2). Mas multiplicar por 3 geralmente não é. Quando a mantissa é ímpar, multiplicar por 3 exigiria mais um bit na nova mantissa. Esse bit é perdido, você obtém um float cujo valor é ligeiramente menor ou ligeiramente maior que 3 vezes o valor de x. Então, quando você subtrai, um dos dois valores pode já ser "impreciso". A subtração também pode levar a um resultado geral "impreciso", ou a subtração pode ser imprecisa também e cancelar a imprecisão anterior, de modo que você obtém exatamente x. Mas o problema é o 3*x, não a subtração. Quando 3*xtambém é exato, então, assim como no 2*x - xcaso, todas as operações são exatas e o resultado geral é exatamente x.

    Como a subtração é capaz de fazer o cálculo para que o resultado seja o valor mais próximo representável por float? Eu acho que geralmente com alguns bits extras ou inteligência durante o cálculo. Mas eu não acho que o padrão defina como as implementações devem calcular o resultado corrigido, ele só se importa com *que" elas o façam.

    • 0

relate perguntas

  • Como divido o loop for em 3 quadros de dados individuais?

  • Como verificar se todas as colunas flutuantes em um Pandas DataFrame são aproximadamente iguais ou próximas

  • Como funciona o "load_dataset", já que não está detectando arquivos de exemplo?

  • Por que a comparação de string pandas.eval() retorna False

  • Python tkinter/ ttkboostrap dateentry não funciona quando no estado somente leitura

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve