web-dev-qa-db-ja.com

Ruby整数の場合、floatをintに丸めます

Rubyでは、floatが整数の場合はintに変換したいと思います。例えば

a = 1.0
b = 2.5

a.to_int_if_whole # => 1
b.to_int_if_whole # => 2.5

基本的に、小数点のない数字に「.0」を表示しないようにしています。エレガントな(または組み込みの)方法を探しています

def to_int_if_whole(float)
  (float % 1 == 0) ? float.to_i : float
end
27
Eric Wright

これは、私が望むように機能することになったソリューションです。

class Float
  alias_method(:original_to_s, :to_s) unless method_defined?(:original_to_s)

  def is_whole?
    self % 1 == 0
  end

  def to_s
    self.is_whole? ? self.to_i.to_s : self.original_to_s
  end
end

このようにして、必要に応じてis_whole?ロジック(tadmanが最も洗練されているようです)を更新できます。これにより、Floatが文字列に出力する場所(フォームなど)で、希望どおりに表示されるようになります。 to(つまり、最後にゼロがない)。

あなたのアイデアをみんなに感謝します-彼らは本当に助けてくれました。

5
Eric Wright

それへの1つの簡単な方法は次のとおりです。

class Float
  def prettify
    to_i == self ? to_i : self
  end
end

それは理由です:

irb> 1.0 == 1
=> true
irb> 1 == 1.0
=> true

次に、次のことができます。

irb> 1.0.prettify
=> 1

irb> 1.5.prettify
=> 1.5
50
Yehuda Katz

ワンライナースプリント...

sprintf("%g", 5.0)
=> "5"

sprintf("%g", 5.5)
=> "5.5"
47
Paul Sturgess

Rubyについてはよくわかりません。

しかし、これはdisplayの問題です。使用しているライブラリに、数値を文字列に変換するときに数値をフォーマットする方法がない場合、私は非常に驚きます。

必要なことを正確に実行するキャッチオールフォーマットオプションがない場合もありますが、floatが整数のfloat表現である場合はtrueを返し、それ以外の場合はfalseを返すメソッドを設定できます。作成するフォーマットルーチン内で(したがって、これを1か所で行うだけで済みます)、これがtrueかfalseかに基づいてフォーマットを変更するだけです。

This は、数値を表示するときに小数点以下に表示される桁数を制御する方法について説明しています。

浮動小数点表現の複雑さに注意してください。数学は答えが3であると言うかもしれませんが、あなたは3.000000000000000000001を得るかもしれません。デルタを使用して、数値がほぼ整数であるかどうかを確認することをお勧めします。

3
colithium

Railsを使用している場合は、ヘルパーnumber_to_roundedをオプションstrip_insignificant_zerosとともに使用できます。次に例を示します。

ActiveSupport::NumberHelper.number_to_rounded(42.0, strip_insignificant_zeros: true)

またはこのように:

42.0.to_s(:rounded, strip_insignificant_zeros: true)
2
Igor Kapkov

私は上記の投稿に同意する傾向がありますが、これを行う必要がある場合:

(float == float.floor) ? float.to_i : float
2
Kuwa

これが教育目的で提供された私の恐ろしくハックな実装です:

class Float
  def to_int_if_whole(precision = 2)
    ("%.#{precision}f" % self).split(/\./).last == '0' * precision and self.to_i or self
  end
end

puts 1.0.to_int_if_whole # => 1
puts 2.5.to_int_if_whole # => 2.5
puts 1.9999999999999999999923.to_int_if_whole # => 2

Sprintfスタイルの呼び出しを使用する理由は、Float#roundメソッドよりもはるかに確実に浮動小数点近似を処理するためです。

1
tadman

Rubyについてもよくわかりません。

しかし、C++では、これを行います。

bool IsWholeNumber( float f )
{
    const float delta = 0.0001;
    int i = (int) f;
    return (f - (float)i) < delta;
}

そして、それに基づいて出力精度をフォーマットします。

0
Geerad