66 pontos por GN⁺ 2025-08-18 | Ainda não há comentários. | Compartilhar no WhatsApp
  • Armadilhas nada intuitivas em que desenvolvedores costumam cair são organizadas para apresentar as causas de bugs que tendem a ocorrer com facilidade
  • Aborda problemas frequentes em várias tecnologias, como HTML, CSS, Unicode/codificação de texto, ponto flutuante e tempo
  • Enfatiza que diferenças sutis de sintaxe e comportamento em cada linguagem e framework podem gerar mal-entendidos ou erros
  • Explica com exemplos as armadilhas que podem surgir em ambientes reais de produção em áreas centrais de backend, como concorrência, redes e bancos de dados
  • Por meio de vários exemplos e links de referência, orienta sobre situações problemáticas, formas de resolvê-las e melhorias para comportamentos inesperados

HTML e CSS

  • Valor padrão de min-width em Flexbox/Grid

    • min-width é auto por padrão
    • min-width: auto é determinado pelo tamanho do conteúdo e tem precedência sobre flex-shrink, overflow: hidden, width: 0, max-width: 100%
    • Recomendação: declarar min-width: 0
  • Diferença entre horizontal e vertical no CSS

    • width: auto tenta preencher o espaço do elemento pai, enquanto height: auto se ajusta ao conteúdo
    • width: auto de elementos inline, inline-block e float não se expande
    • margin: 0 auto centraliza na horizontal, margin: auto 0 não centraliza na vertical (mas em flex-direction: column, a centralização vertical é possível)
    • Colapso de margem só ocorre na vertical
    • Se a direção do layout mudar, como em writing-mode: vertical-rl, o comportamento também se inverte
  • Block Formatting Context (BFC)

    • É possível criar um BFC com display: flow-root (também é possível com overflow: hidden/auto/scroll, display: table etc., mas há efeitos colaterais)
    • Um BFC pode evitar que margens verticais de irmãos adjacentes se sobreponham ou que a margem do filho “vaze” para fora do pai
    • Se o pai contiver apenas filhos com float, sua altura colapsa para 0 → isso pode ser corrigido com BFC
    • Se houver border ou padding, não ocorre colapso de margem
  • Stacking Context

    • Condições que criam um novo stacking context
      • Propriedades de renderização como transform, filter, perspective, mask, opacity etc.
      • position: fixed ou sticky
      • z-index definido + posicionamento absolute/relative
      • z-index definido + elemento dentro de flexbox/grid
      • isolation: isolate
    • Características
      • z-index só se aplica dentro do stacking context
      • As coordenadas de position: absolute/fixed se baseiam no ancestral posicionado mais próximo
      • sticky não funciona atravessando o stacking context
      • Mesmo overflow: visible é recortado pelo stacking context
      • background-attachment: fixed é posicionado com base no stacking context
  • Unidades de viewport

    • Em navegadores móveis, quando a barra de endereço/barra de navegação some da tela ao rolar, o valor de 100vh muda
    • Solução mais recente: usar 100dvh
  • Referência para Absolute Position

    • position: absolute não se baseia no pai, mas no ancestral relative/absolute ou stacking context mais próximo
  • Comportamento do blur

    • backdrop-filter: blur não leva em conta os elementos ao redor
  • Float sem efeito

    • Se o pai for flex ou grid, o float do filho não tem efeito
  • width/height em porcentagem

    • Não funciona se o tamanho do pai não tiver sido definido previamente (para evitar referência circular)
  • Características de elementos inline

    • display: inline ignora width, height, margin-top e margin-bottom
  • Tratamento de whitespace

    • Por padrão, quebras de linha em HTML são tratadas como espaço, e espaços consecutivos são reduzidos a um só
    • <pre> evita a redução de espaços, mas tem um comportamento peculiar no início/fim
    • Em geral, espaços no início/fim do conteúdo são ignorados, mas <a> é uma exceção
    • Espaços/quebras de linha entre inline-block aparecem como espaçamento real (isso não ocorre em flex/grid)
  • text-align

    • Aplica-se ao alinhamento de texto e elementos inline, mas não ao alinhamento de elementos block
  • box-sizing

    • O valor padrão é content-box → não inclui padding/border
    • Com width: 100% + padding, o elemento pode ultrapassar a área do pai
    • Solução: box-sizing: border-box
  • Cumulative Layout Shift

    • Se <img> não tiver os atributos width e height, o atraso no carregamento da imagem pode causar instabilidade no layout
    • Recomendação: definir os atributos para evitar CLS
  • Requisições de rede de download de arquivos no Chrome

    • Não aparecem no painel Network do DevTools (são processadas em outra aba)
    • Se precisar analisar, use chrome://net-export/
  • Problemas de parsing de JavaScript dentro de HTML

    • Em casos como <script>console.log('</script>')</script>, o primeiro </script> é interpretado como tag de fechamento
    • Referência: Safe JSON in script tags

Unicode e codificação de texto

  • Code points e grapheme clusters

    • Grapheme cluster é a “unidade de caractere” na GUI
    • Em caracteres ASCII visíveis, 1 code point = 1 grapheme cluster
    • Um emoji pode ser um único grapheme cluster composto por vários code points
    • Em UTF-8, um code point ocupa de 1 a 4 bytes, e a quantidade de bytes não coincide com a de code points
    • Em UTF-16, um code point ocupa 2 ou 4 bytes (par substituto, surrogate pair)
    • O padrão não impõe limite ao número de code points dentro de um cluster, mas implementações costumam ter limites por desempenho
  • Diferenças no comportamento de strings por linguagem

    • Rust: internamente usa strings UTF-8, len() retorna número de bytes, indexação direta não é possível, chars().count() retorna o número de code points, valida rigorosamente a validade do UTF-8
    • Golang: string é, na prática, um array de bytes; comprimento e indexação são em bytes; UTF-8 é o mais usado
    • Java, C#, JS: baseados em UTF-16, medem comprimento em unidades de 2 bytes, e a indexação também é nessa base; há surrogate pairs
    • Python: len() retorna o número de code points, e a indexação retorna uma string contendo um code point
    • C++: std::string não impõe restrições de codificação, funciona como um vetor de bytes, e comprimento/indexação são em bytes
    • Entre as linguagens mencionadas, nenhuma mede comprimento/faz indexação por grapheme cluster
  • BOM (Byte Order Mark)

    • Alguns arquivos de texto têm BOM; por exemplo, EF BB BF indica codificação UTF-8
    • É usado principalmente no Windows, e softwares fora do ecossistema Windows podem não conseguir lidar com BOM
  • Outros cuidados

    • Ao converter dados binários em string, partes inválidas são substituídas por � (U+FFFD)
    • Existem confusable characters (caracteres que parecem muito semelhantes entre si)
    • Normalização (Normalization): por exemplo, é pode ser representado como U+00E9 (um único code point) ou U+0065+U+0301 (dois code points)
    • Existem zero-width characters e invisible characters
    • Diferença de quebra de linha: no Windows é CRLF \r\n, no Linux/MacOS é LF \n
    • Unificação de Han (Han unification): caracteres com formas ligeiramente diferentes em cada idioma usam o mesmo code point
      • A fonte renderiza corretamente incluindo variantes por idioma
      • Em internacionalização, é necessário selecionar a variante de fonte correta

Ponto flutuante (Floating point)

  • Propriedades de NaN

    • NaN não é igual a nenhum valor, incluindo ele mesmo (NaN == NaN é sempre false)
    • NaN != NaN é sempre true
    • O resultado de operações que incluem NaN geralmente se propaga como NaN
  • Valores especiais

    • Existem +Inf e -Inf, diferentes de NaN
    • -0.0 é um valor distinto de +0.0
      • Em operações de comparação eles são iguais, mas em alguns cálculos se comportam de forma diferente
      • Exemplo: 1.0 / +0.0 == +Inf, 1.0 / -0.0 == -Inf
  • Compatibilidade com JSON

    • O padrão JSON não permite NaN nem Inf
      • Em JS, JSON.stringify converte NaN e Inf em null
      • Em Python, json.dumps(...) imprime NaN e Infinity como estão (violando o padrão)
        • Com a opção allow_nan=False, ocorre ValueError se houver NaN/Inf
      • Em Golang, json.Marshal retorna erro se houver NaN/Inf
  • Problemas de precisão

    • Comparação direta de ponto flutuante pode falhar → recomenda-se a forma abs(a - b) < ε
    • Em JS, todos os números são tratados como ponto flutuante
      • O intervalo seguro de inteiros é -(2^53 - 1) ~ 2^53 - 1
      • Fora desse intervalo, a representação de inteiros fica imprecisa
      • Para inteiros grandes, recomenda-se usar BigInt
      • Se JSON contiver inteiros além do intervalo seguro, o valor resultante de JSON.parse pode ser impreciso
      • Timestamps em milissegundos são seguros até o ano 287.396; em nanossegundos já causam problema
  • Leis de operação que não se aplicam

    • Dependendo da ordem das operações, por perda de precisão, associatividade e distributividade não valem estritamente
    • Operações paralelas (multiplicação de matrizes, soma etc.) podem produzir resultados não determinísticos
  • Desempenho

    • Divisão é muito mais lenta que multiplicação
    • Ao dividir várias vezes pelo mesmo número, é possível otimizar calculando primeiro o recíproco e multiplicando
  • Diferenças conforme o hardware

    • Suporte a FMA (Fused Multiply-Add): alguns hardwares fazem cálculos intermediários com maior precisão
    • Tratamento de subnormal range: hardwares modernos suportam, mas alguns antigos tratam como 0
    • Diferenças de modo de arredondamento
      • Existem modos como RNTE (arredondar para o par mais próximo), RTZ (truncar para 0) etc.
      • Em x86/ARM, isso pode ser configurado como estado mutável local à thread
      • Em GPU, o modo de arredondamento varia por instrução
    • Diferenças no comportamento de funções matemáticas como trigonométricas e logaritmos
    • x86 tem FPU legada de 80 bits e rounding mode por núcleo → não recomendado usar
    • Além disso, vários outros fatores podem fazer o resultado de ponto flutuante variar conforme o hardware
  • Como melhorar a precisão

    • Montar um grafo de cálculo mais raso (reduzir cadeias longas de multiplicação)
    • Evitar casos em que valores intermediários fiquem muito grandes ou muito pequenos
    • Aproveitar operações de hardware como FMA

Tempo (Time)

  • Segundo intercalar (Leap second)

    • O timestamp Unix ignora segundos intercalares
    • Quando ocorre um segundo intercalar, o tempo pode se alongar ou encurtar na região ao redor (Leap smear)
  • Fuso horário (Time zone)

    • UTC e timestamp Unix são comuns no mundo todo
    • Horários legíveis por humanos dependem do fuso horário local
    • Recomenda-se armazenar timestamps no banco de dados e converter na UI
  • Horário de verão (DST)

    • Em algumas regiões, o relógio é ajustado em 1 hora durante o verão
  • Sincronização NTP

    • Durante a sincronização, pode acontecer de o tempo “voltar para trás”
  • Configuração de fuso horário do servidor

    • Recomenda-se configurar servidores em UTC
    • Em sistemas distribuídos, diferenças de fuso entre nós causam problemas
    • Após mudar o fuso do sistema, pode ser necessário reconfigurar ou reiniciar o banco de dados
  • Relógio de hardware vs relógio do sistema

    • O relógio de hardware não tem conceito de fuso horário
    • Linux: trata o relógio de hardware como UTC
    • Windows: trata o relógio de hardware como horário local

Java

  • == compara referências de objetos; para comparar o conteúdo do objeto, é preciso usar .equals
  • Se equals e hashcode não forem sobrescritos, a identidade do objeto em map/set é julgada com base na referência
  • Se o conteúdo de um objeto usado como chave de map ou elemento de set for alterado, o comportamento do contêiner quebra
  • Métodos que retornam List<T> podem, dependendo do caso, retornar um ArrayList mutável ou Collections.emptyList() imutável; ao modificar o segundo, ocorre UnsupportedOperationException
  • Existem métodos que retornam Optional<T> mas devolvem null (não recomendado)
  • Se houver return em um bloco finally, uma exceção ocorrida em try ou catch é ignorada e o valor retornado por finally prevalece
  • Existem bibliotecas que ignoram interrupt, e a inicialização de classes, incluindo IO, pode ser quebrada por interrupt
  • Em thread pool, exceções de tasks passadas com .submit() não são registradas em log por padrão e só podem ser verificadas via future; se o future for ignorado, não há como ver a exceção
    • Tarefas scheduleAtFixedRate param silenciosamente quando ocorre exceção
  • Se um literal numérico começa com 0, ele é tratado como octal (0123 → 83)
  • O depurador chama .toString() de variáveis locais, e toString() em algumas classes tem efeitos colaterais, então o comportamento do código pode mudar durante a depuração (pode ser desativado na IDE)

Golang

  • append() reutiliza memória quando há folga de capacity; ao fazer append em um subslice, é possível sobrescrever até a memória do pai
  • defer é executado quando a função retorna, não quando o escopo do bloco termina
  • defer captura variáveis mutáveis
  • Sobre nil
    • nil slice e empty slice são diferentes
    • string não pode ser nil, só existe string vazia
    • nil map permite leitura, mas não escrita
    • comportamento peculiar de nil em interface: se o data pointer é null mas a type info não é null, então não é igual a nil
  • Dead wait: existem casos reais desse tipo de bug de concorrência em Go
  • Existem vários tipos de timeout, tratados em detalhe em net/http

C/C++

  • Ao armazenar ponteiros para elementos de std::vector, se o vector crescer pode ocorrer realocação, invalidando os ponteiros
  • Um std::string criado a partir de uma string literal pode ser um objeto temporário; chamar c_str() nesse caso é arriscado
  • Modificar um contêiner durante a iteração pode invalidar iterators
  • std::remove não remove de fato os elementos, apenas os reorganiza; para remover é preciso usar erase
  • Se um literal numérico começa com 0, ele é tratado como octal (0123 → 83)
  • Undefined behavior (UB): durante a otimização, UB pode ser alterado livremente, então depender disso é perigoso
    • Acesso a memória não inicializada é UB
    • Ao converter char* para ponteiro de struct, acessar antes do início da vida útil do objeto é UB; recomenda-se inicializar com memcpy
    • Acesso inválido à memória (como ponteiro nulo) é UB
    • Overflow/underflow de inteiro é UB (tipos unsigned podem sofrer underflow abaixo de 0)
    • Aliasing: se ponteiros de tipos diferentes referenciam a mesma memória, pode ocorrer UB pela strict aliasing rule
      • Exceções: 1) tipos em relação de herança 2) conversão para char*, unsigned char*, std::byte* (a conversão inversa não se aplica)
      • Para conversão forçada, recomenda-se memcpy ou std::bit_cast
    • Acesso a memória não alinhada é UB
  • Alinhamento de memória
    • Inteiros de 64 bits devem estar em endereços divisíveis por 8
    • Em ARM, acesso não alinhado pode causar crash
    • Interpretar diretamente um buffer de bytes como struct pode gerar problemas de alinhamento
    • O alinhamento pode criar padding em structs e desperdiçar memória
    • Algumas instruções SIMD (como AVX) só conseguem processar dados alinhados, normalmente exigindo alinhamento de 32 bytes

Python

  • Argumentos padrão de função não são recriados a cada chamada; o valor inicial fica armazenado

SQL Databases

  • Tratamento de Null

    • x = null não funciona; deve-se usar x is null
    • Null não é igual a si mesmo (semelhante a NaN)
    • Índices unique permitem Null duplicado (exceto no Microsoft SQL Server)
    • Em select distinct, a forma de tratar Null varia conforme o banco
    • count(x) e count(distinct x) ignoram linhas com valor Null
  • Comportamento geral

    • Conversão implícita de datas pode depender de timezone
    • Join complexo + distinct pode ser mais lento do que consulta aninhada
    • No MySQL(InnoDB), se um campo string não estiver em utf8mb4, inserir caracteres UTF-8 de 4 bytes causará erro
    • O MySQL(InnoDB) por padrão não diferencia maiúsculas de minúsculas
    • O MySQL(InnoDB) permite conversão implícita: select '123abc' + 1; → 124
    • Gap lock no MySQL(InnoDB) pode causar deadlock
    • No MySQL(InnoDB), quando group by e as colunas de select não batem, o resultado pode ser não determinístico
    • No SQLite, se não estiver em modo strict, o tipo do campo tem pouca importância
    • Foreign key pode gerar locks implícitos e causar deadlock
    • O locking pode quebrar o isolamento repeatable read dependendo do banco
    • Bancos SQL distribuídos podem não oferecer suporte a locking ou ter comportamentos peculiares (varia conforme o banco)
  • Desempenho/operação

    • O problema de N+1 query não aparece no slow query log porque cada query individual é rápida
    • Transações de longa duração podem causar problemas de lock etc. → recomenda-se encerrá-las rapidamente
    • Casos de lock na tabela inteira
      • No MySQL 8.0+, ao adicionar unique index/foreign key, na maioria dos casos o processamento concorrente é possível
      • Versões antigas do MySQL podem causar lock da tabela inteira
      • Se mysqldump não usar a opção --single-transaction, ocorre read lock na tabela inteira
      • No PostgreSQL, create unique index ou alter table ... add foreign key causam read lock na tabela inteira
        • Como evitar: usar create unique index concurrently
        • Para foreign key, usar ... not valid e depois validate constraint
  • Consultas de intervalo

    • Intervalos que não se sobrepõem:
      • A condição simples p >= start and p <= end é ineficiente (mesmo com índice composto)
      • Forma eficiente:
        select *   
        from (select ... from ranges where start <= p order by start desc limit 1)   
        where end >= p  
        
        (apenas o índice da coluna start é necessário)
    • Intervalos que podem se sobrepor:
      • Com um índice B-tree comum, é ineficiente
      • Recomenda-se spatial index no MySQL e GiST no PostgreSQL

Concurrency and Parallelism

  • volatile

    • volatile não substitui lock nem fornece atomicidade
    • Dados protegidos por lock não precisam de volatile (o lock garante memory order)
    • C/C++: volatile só impede algumas otimizações; não adiciona memory barrier
    • Java: acesso a volatile fornece sequentially-consistent ordering (quando necessário, a JVM insere memory barrier)
    • C#: acesso a volatile fornece release-acquire ordering (quando necessário, o CLR insere memory barrier)
    • Pode evitar otimizações incorretas relacionadas à reordenação de leitura/escrita de memória
  • TOCTOU (Time-of-check to time-of-use) problema

  • Tratamento de restrições na camada de aplicação em bancos SQL

    • Quando restrições que não podem ser expressas com um simples unique index (ex.: unicidade entre duas tabelas, unicidade condicional, unicidade dentro de um período) são impostas pela aplicação:
      • MySQL(InnoDB): no nível repeatable read, fazer select ... for update antes do insert e, se houver índice na coluna única, isso funciona graças ao gap lock (mas gap lock pode causar deadlock sob alta carga → é preciso detecção de deadlock e retry)
      • PostgreSQL: no nível repeatable read, a mesma lógica é insuficiente em cenários concorrentes (problema de write skew)
        • Soluções:
          • usar nível de isolamento serializable
          • usar restrições do banco em vez da aplicação
            • unicidade condicional → partial unique index
            • unicidade entre duas tabelas → inserir dados duplicados em uma tabela separada e aplicar unique index
            • exclusividade por período → range type + exclude constraint
  • Contagem atômica de referências

    • Se muitas threads alteram com frequência o mesmo contador, como em Arc e shared_ptr, pode haver queda de desempenho
  • Read-write lock

    • Algumas implementações não suportam upgrade de read lock para write lock
    • Tentar obter write lock enquanto se mantém um read lock pode causar deadlock

Comum em muitas linguagens

  • Falta de verificação de Null/None/nil é uma causa comum de erros
  • Ao modificar um contêiner durante um loop, pode ocorrer corrida de dados em thread única
  • Erro ao compartilhar dados mutáveis: ex.) em Python, [[0] * 10] * 10 não cria corretamente um array 2D
  • (low + high) / 2 pode causar overflow → a forma segura é low + (high - low) / 2
  • Avaliação de curto-circuito (short circuit): a() || b() não executa b se a for true; a() && b() não executa b se a for false
  • O padrão do profiler inclui apenas CPU time → esperas de DB etc. não aparecem no flamegraph, o que pode gerar interpretações erradas
  • O dialeto de expressões regulares varia entre linguagens → uma regex que funciona em JS pode não funcionar em Java

Linux and bash

  • Depois de mudar de diretório, pwd mostra o caminho original; o caminho real é mostrado por pwd -P
  • cmd > file 2>&1 → stdout+stderr vão para o arquivo; cmd 2>&1 > file → só stdout vai para o arquivo, stderr permanece como está
  • Nomes de arquivo diferenciam maiúsculas de minúsculas (diferente do Windows)
  • Arquivos executáveis têm um sistema de capabilities (getcap para verificar)
  • Risco com variável unset: se DIR estiver unset, rm -rf $DIR/ pode virar rm -rf / → dá para evitar com set -u
  • Aplicação do ambiente: para aplicar um script no shell atual, use source script.sh → para aplicar permanentemente, adicione em ~/.bashrc
  • O Bash faz cache de comandos: ao mover arquivos dentro de $PATH, pode ocorrer ENOENT → atualize o cache com hash -r
  • Ao usar variáveis sem aspas, quebras de linha são tratadas como espaços
  • set -e: encerra o script imediatamente em caso de erro, mas não funciona dentro de condicionais (||, &&, if)
  • Conflito entre livenessProbe do K8s e debugger: um debugger com breakpoint pode parar o app inteiro e fazer o health check falhar → o Pod pode ser encerrado

React

  • Modificar state diretamente no código de renderização
  • Usar Hook dentro de if/loop → violação das regras
  • Omitir valores necessários no dependency array do useEffect
  • Omitir o código de clean up no useEffect
  • Armadilha de closure: bugs causados por capturar um state antigo
  • Alterar dados no lugar errado → componente impuro
  • Deixar de usar useCallback → rerenderizações desnecessárias
  • Passar valores não memoizados para componentes memoizados invalida a otimização de memo

Git

  • Rebase reescreve o histórico

    • depois de um rebase, um push normal gera conflito → é necessário fazer force push
    • ao mudar o histórico de uma branch remota, também use pull --rebase
    • --force-with-lease pode, em alguns casos, evitar sobrescrever commits de outros desenvolvedores, mas se você só fizer fetch e não pull, essa proteção não funciona
  • Problema ao reverter merge

    • reverter um merge tem efeito incompleto → ao fazer merge da mesma branch novamente, pode não haver mudança alguma
    • solução: reverter o revert ou usar um método mais limpo (backup → reset → cherry-pick → force push)
  • Cuidados relacionados ao GitHub

    • mesmo que você sobrescreva com force push após commitar um secret como chave de API, o histórico continua no GitHub
    • se um repositório privado B for fork de um privado A, e A virar público, o conteúdo de B também fica público (e continua acessível mesmo após a exclusão)
  • git stash pop: se houver conflito, o stash não é removido

  • .DS_Store é criado automaticamente pelo macOS → recomenda-se adicionar **/.DS_Store ao .gitignore

Networking

  • Alguns roteadores e firewalls encerram silenciosamente conexões TCP ociosas → isso pode invalidar pools de conexão de clientes HTTP e DB → solução: configurar TCP keepalive
  • O resultado do traceroute tem baixa confiabilidade → em alguns casos, tcptraceroute é mais útil
  • TCP slow start pode aumentar a latência → pode ser resolvido desativando tcp_slow_start_after_idle
  • Problema de sticky packet no TCP: o algoritmo de Nagle atrasa o envio de pacotes → pode ser resolvido ativando TCP_NODELAY
  • Ao colocar um backend atrás do Nginx, é necessário configurar a reutilização de conexões → sem isso, em ambientes de alta carga, conexões podem falhar por falta de portas internas
  • O Nginx faz buffering de pacotes por padrão → isso pode causar atraso em SSE (EventSource)
  • O padrão HTTP não proíbe body em requisições GET e DELETE → alguns usam body, mas muitas bibliotecas e servidores não oferecem suporte
  • É possível hospedar vários sites em um único IP → a distinção é feita pelo header HTTP Host e pelo SNI do TLS → há sites que não funcionam com acesso direto por IP
  • CORS: ao fazer requisições para outra origin, o navegador bloqueia o acesso à resposta → o servidor precisa definir o header Access-Control-Allow-Origin
    • configurações adicionais são necessárias ao incluir envio de cookies
    • se frontend e backend estiverem no mesmo domínio e porta, não há problema de CORS

Other

  • Cuidados com YAML

    • YAML é sensível a espaçoskey:value é erro; key: value é o correto
    • o código de país NO, se usado sem aspas, pode ser interpretado como false
    • um hash de commit do Git sem aspas pode ser convertido em número
  • Problemas de CSV no Excel

    • ao abrir um CSV, o Excel faz conversões automáticas
      • conversão de data: 1/2, 1-22-Jan
      • conversão imprecisa de números grandes: 1234567890123456789012345678901234500000
    • isso acontece porque o Excel trata números internamente como floating point
    • há casos em que isso alterou incorretamente o nome de gene SEPT1

Ainda não há comentários.

Ainda não há comentários.