round redondear float decimales ruby floating-point rounding bigdecimal floating-point-precision

ruby - redondear - ¿Por qué mis objetos BigDecimal se inicializan con errores de redondeo inesperados?



math round java dos decimales (1)

En Ruby 2.2.0, ¿por qué hace:

BigDecimal.new(34.13985572755337, 9)

igual a 34.0 pero

BigDecimal.new(34.13985572755338, 9)

igual 34.1398557 ?

Tenga en cuenta que estoy ejecutando esto en una máquina de 64 bits.


Inicializar con cadenas en lugar de flotadores

En general, no se puede obtener un comportamiento confiable con flotadores. Está cometiendo el error de inicializar sus BigDecimals con valores de Flotante en lugar de valores de Cadena, lo que introduce cierta imprecisión desde el principio. Por ejemplo, en mi sistema de 64 bits:

float1 = 34.13985572755337 float2 = 34.13985572755338 # You can use string literals here, too, if your Float can''t be properly # represented. For example: # # BigDecimal.new("34.13985572755337", 9) # # would be safer, but Float#to_s works fine with the provided corpus. bd1 = BigDecimal.new(float1.to_s, 9) bd2 = BigDecimal.new(float2.to_s, 9) bd1.to_s #=> "0.3413985572755337E2" bd2.to_s #=> "0.3413985572755338E2" bd1.to_f == float1 #=> true bd2.to_f == float2 #=> true

Este es uno de esos casos donde importa la representación interna de los argumentos. Por lo tanto, su millaje variará dependiendo de cómo inicialice su objeto.