300 votes

Flottant vs décimal dans ActiveRecord

Parfois, Activerecord types de données me confondre. Err, souvent. Un de mes éternelles questions est, pour un cas donné,

Dois-je utiliser :decimal ou :float?

J'ai souvent rencontré ce lien, ActiveRecord: :décimal vs :float?, mais les réponses ne sont pas tout à fait assez clair pour moi, pour être certain:

J'ai vu beaucoup de discussions où les gens de recommander à plat pour ne plus utiliser de flotteur et de toujours utiliser la virgule. J'ai aussi vu des suggestions faites par certains les gens à utiliser float pour les applications scientifiques.

Voici quelques exemples de cas:

  • Géolocalisation/latitude/longitude: -45.756688, 120.5777777, ...
  • Ratio/pourcentage: 0.9, 1.25, 1.333, 1.4143, ...

Je l'ai utilisé, :decimal dans le passé, mais j'ai trouvé traiter avec BigDecimal objets en Ruby était inutilement maladroite par rapport à un flotteur. Je sais aussi que je peux utiliser :integer pour représenter de l'argent/cents, par exemple, mais il n'a pas tout à fait adapté pour d'autres cas, par exemple lorsque les quantités dans lesquelles la précision pourrait changer au fil du temps.

  • Quels sont les avantages/inconvénients de l'utilisation de chacun?
  • Ce serait quelques bonnes règles de base à savoir quel type d'utilisation?

457voto

Iuri G. Points 3809

Je me souviens de mon professeur de fac d'informatique disant de ne jamais utiliser les flotteurs de la monnaie.

La raison en est que la façon dont la spécification IEEE définit flotteurs en format binaire. Fondamentalement, il stocke de signer, de fraction et exposant de façon à représenter un Flotteur. C'est comme une notation scientifique pour les binaires (quelque chose comme +1.43*10^2). De ce fait, il est impossible de stocker les fractions et les décimales dans Flotter exactement.

C'est pourquoi il existe un format Décimal. Si vous faites cela:

irb:001:0> "%.47f" % (1.0/10)
=> "0.10000000000000000555111512312578270211815834045" # not "0.1"!

alors que si vous venez de le faire

irb:002:0> (1.0/10).to_s
=> "0.1" # the interprer rounds the number for you

Donc, si vous faites affaire avec de petites fractions, comme le compoundage intérêts, ou peut-être même de la géolocalisation, je vous recommande fortement de format Décimal, depuis au format décimal 1.0/10 est exactement 0.1.

Toutefois, il convient de noter qu'en dépit d'être moins précis, les flotteurs sont traitées plus rapidement. Voici un indice:

require "benchmark" 
require "bigdecimal" 

d = BigDecimal.new(3) 
f = Float(3)

time_decimal = Benchmark.measure{ (1..10000000).each { |i| d * d } } 
time_float = Benchmark.measure{ (1..10000000).each { |i| f * f } }

puts time_decimal 
#=> 6.770960 seconds 
puts time_float 
#=> 0.988070 seconds

Réponse

Utiliser float lorsque vous ne vous inquiétez pas au sujet de la précision de trop. Par exemple, certains scientifiques les simulations et les calculs seulement besoin jusqu'à 3 ou 4 chiffres significatifs. Ceci est utile dans le commerce hors de l'exactitude de la vitesse. Car ils n'ont pas besoin d'une grande précision autant que la vitesse, qu'ils allaient utiliser des float.

Utiliser la virgule si vous travaillez avec des numéros qui ont besoin d'être précis et de la somme d'un nombre correct (comme le compoundage intérêts et liée à l'argent des choses). Rappelez-vous: si vous avez besoin de précision, alors vous devriez toujours utiliser la virgule.

21voto

ryan0 Points 639

Dans Rails 3.2.18, : Decimales se transforme en : entier lorsque vous utilisez SQL Server, mais il fonctionne très bien dans SQLite. Passer à : flotteur résolu ce problème pour nous.

La leçon apprise, c’est « toujours utiliser homogènes développement et déploiement de bases de données ! »

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X