Se eu definir a escala de 175% nas configurações do Gnome, o valor será salvo como 1.7518248558044434
em ~/.config/monitors.xml
:
<monitors version="2">
<configuration>
<logicalmonitor>
<x>0</x>
<y>0</y>
<scale>1.7518248558044434</scale>
<primary>yes</primary>
<monitor>
<monitor spec>
<connector>DP-3</connector>
Por que é tão? A princípio, pensei que poderia ser devido a um erro de arredondamento de ponto flutuante, mas 1,75 é um daqueles números felizes cujo valor exato pode ser expresso.
Gnomo Wayland 43.3
Os fatores de escala predefinidos (100%, 125%, etc.) são ajustados para os valores mais próximos que fornecem um número inteiro de pixels virtuais de pré-dimensionamento horizontal e verticalmente para sua resolução; a julgar pelo seu valor de 1,7518248558044434, provavelmente é 2192 x 1233 e você tem uma tela de 3840 x 2160.
Além disso, por que a largura que você calcularia com esse valor,
3840/1.7518248558044434 = 2191.9999520937613
, é precisa apenas cerca de quatro casas após o ponto decimal, claramente a escala foi convertida de ponto flutuante de precisão simples (IEEE-754 32 bits). A aproximação de precisão dupla de3840/2192
é mais parecida com1.7518248175182483
, mas se você converter esse valor em precisão simples e voltar para precisão dupla, obterá1.7518248558044434
precisão. Eu fiz isso com Python, conforme sugerido pela resposta https://stackoverflow.com/a/43405711/60422 :Stéphane Chazelas sugere o one-liner correspondente em Perl:
Por que converter um número de ponto flutuante para uma precisão mais alta fornece uma representação decimal com mais dígitos inúteis é o tipo de erro de arredondamento de ponto flutuante a que a pergunta está se referindo - a representação interna do número de ponto flutuante é em binário e portanto, os dígitos após o ponto flutuante internamente (o "ponto binário", já que é binário) representam potência de 2 frações (1/2, 1/4, 1/8 e assim por diante). Um número que você pode expressar em um número finito de casas decimais não tem necessariamente uma representação finita em binário. Para saber mais sobre isso, consulte: https://stackoverflow.com/a/588014/60422
A precisão única geralmente é considerada boa para cerca de 7 algarismos decimais significativos e é isso que estamos vendo aqui.
Para ter uma ideia de como o ajuste do fator de escala realmente funciona, a
get_closest_scale_factor_for_resolution
função inmutter
calcula a largura e a altura virtuais do fator de escala e, se não forem números inteiros, começando com a largura calculada arredondada para baixo, tenta o número inteiro larguras ao redor da calculada em ambos os lados, expandindo para fora um pixel por vez, até encontrar uma largura que forneça um fator de escala ajustado que também tornaria a altura virtual um número inteiro, ou até desistir porque a escala foi saiu do alcance ou do limite de pesquisa. https://gitlab.gnome.org/GNOME/mutter/-/blob/176418d0e7ac6a0418eea46669f33c8e3b03c4bd/src/backends/meta-monitor.c#L1960Se você quer saber por que os desenvolvedores decidiram fazer isso , não tenho a resposta para isso, mas meu palpite é a compatibilidade com versões anteriores: os desenvolvedores estão acostumados com os monitores das pessoas com números inteiros de pixels, e é isso que o existente software lá fora é projetado para.
Outra teoria: o racional do qual 1,7518248558044434 é uma aproximação não é 2192/1233, mas o mais simples 240/137 = 1,7518248175182481... (Para obter um racional mais próximo, você precisaria de numerador e denominador maiores por um fator de 1390. E sim, as representações decimais de múltiplos de 1/137 têm um ciclo de 8 dígitos.) Portanto, existem várias possibilidades para a altura e a largura em pixels que dariam essa proporção, incluindo 2160 x 1233.
Mas, você diz, 240/137 está perto, mas não tão perto. Outra boa aproximação é 3673843/2097152. Para obter um racional mais próximo, você precisaria de um numerador e um denominador maiores por um fator de milhares. 1/2097152 é 2^{-21}. Isso sugere que 240/137 foi armazenado em um ponto flutuante binário com espaço suficiente para 22 bits de mantissa: um bit à esquerda e 21 bits à direita do ponto binário. (Essas contagens de bits negligenciam quaisquer 0s à direita que possam existir.) Em seguida, convertidos em decimal com muito mais precisão do que naquela representação binária.