3

Java/Groovy プログラムに取り組んでいます。ユーザーが入力した数値を保持する double 変数があります。私が本当に知りたいのは、ユーザーが小数点の右側にいくつの数字を入力したかです。何かのようなもの:

double num = 3.14
num.getPlaces() == 2

もちろん、これは double で行うことはできません。これは、IEEE 浮動小数点を使用しており、すべて近似であるためです。

ユーザーが入力した文字列を取得できず、値が格納されている double にしかアクセスできないと仮定すると、その double を BigDecimal またはそのようなものでスクラブして、「実際の」数を取得する方法はありますか?小数位?(ダブルが画面に表示されると、それは正しく表示されるので、少なくともうまく推測する方法があると思いますか?)

4

7 に答える 7

14

いいえ、できません...ユーザーが入力した可能性のあるさまざまな文字列がたくさんあり、すべてが同じ値に解析されるためです。

「実際の」数値は、ユーザーが入力したよりも多くの小数点以下の桁数を持つことはほぼ確実です。たとえば、3.14 は正確に 3.14000000000000124344978758017532527446746826171875 として格納されます。それをユーザーに表示たくないと思います。

問題をより明確にするために、ユーザーが実際に入力したかどうかを double 値から判断することはできません。

3.14
3.140
3.140000
3.14000000000000012434

これらの 4 つの文字列はすべて同じ値を返します。これは、ユーザーが入力したものに戻れない可能性があることを明らかにする必要があります。

可能であれば、解析コードを変更し、全体で使用BigDecimalてください。

于 2009-12-04T20:08:52.890 に答える
3

double で何か奇妙なことが起こっているのは正しいです。出力されるものは、変数の内容と同じではありません。

例えば:

groovy:000> "123.0001".toBigDecimal()
===> 123.0001
groovy:000> "123.0001".toDouble()
===> 123.0001
groovy:000> new BigDecimal("123.0001".toDouble())
===> 123.000100000000003319655661471188068389892578125

double が BigDecimal に渡されるときではなく、文字列を double に変換するときに損傷が発生することに注意してください。double を BigDecimal にフィードすると、実際に double に何が入っているかを簡単に確認できます。toString は嘘をついているからです。

Jon Skeet が指摘するように、ここでは正確さはオプションではありません。ただし、画面に表示される値が double で toString を呼び出した結果であると仮定すると、次のように、double の toString バージョンよりも間違いのない bigDecimal を取得できるはずです。

groovy:000> d = "123.0001".toDouble()
===> 123.0001
groovy:000> d.toString()
===> 123.0001
groovy:000> new BigDecimal(d.toString())
===> 123.0001

したがって、BigDecimal を含める必要はありません。実際には、次のようなことができます。

groovy:000> d = 123.0001
===> 123.0001
groovy:000> s = d.toString()
===> 123.0001
groovy:000> s.substring(s.indexOf('.')).length() - 1
===> 4

コメントを編集して無効にして申し訳ありません。

ところで、これはスティーブの答えに近いもので、グルーヴィーに翻訳されています。(小数点にピリオドを使用していないロケールが台無しになっているマシンでこれを実行すると、0 を返すよりも爆破したいので、小数点が見つからないというテストを行いました)

def getPlaces(d) {
    s = d.toString()
    s.substring(s.indexOf(".")).length() - 1
}
于 2009-12-04T20:08:54.200 に答える
2

はい、できます。少なくとも、時々間違った結果が得られることを気にしないのであれば。ユーザーは怠け者であり、入力した有効桁数は最大 12 桁までであると想定する必要があります。

次に、次の操作を行います。

  • コンストラクターで指定された double を使用して BigDecimal を作成します。これにより、double が正確な 10 進数表現に変換されます。

  • 分数のみを取得します。

  • BigDecimal.toString() を取得し、3 つ以上連続する '0' または '9' の数字を見つけます。

  • これらの 3 桁の後の端数を切り捨てます。数字が9桁の場合は、最後に「1」を追加します。その後、末尾のゼロをすべて削除します。

  • 残りの小数桁を数えます

警告: これは少し遅いかもしれません。

double の有効ビット数のみが必要な場合は、はるかに高速かつ簡単に取得できますが、残念ながら、10 進数から 2 進数への変換ではほとんどすべてのビットが使用されます。

于 2009-12-07T22:16:25.493 に答える
1

絶対に double を取得する必要があり、それを実行するための小さなユーティリティ メソッドが必要ない場合は、次のように記述できます。ユーザーが入力した文字列値にアクセスできないとおっしゃいましたが、文字列に変換してこのようなことを行うことができない理由はありますか?

static int getPlaces(double num) {
    String numString = String.valueOf(num);

    return numString.indexOf(".0")==numString.length()-2?0:numString.length()-numString.indexOf(".")-1;
}

次に、あなたの例の代わりに

 num.getPlaces() == 2

できるよ

 getplaces(num) == 2

これが役立つことを願っています..

あなたのコメントを踏まえて、更新してください That the user entered. Good point.

ユーザーが小数点なしの整数 (たとえば 5) のように見えるものを入力し、それを double として受け取った場合、ユーザーが入力したものとは別の何かが得られます。は 5 を入力しますが、5.0 を受け取ります。ユーザーが実際に 5 と 5.0 のどちらを入力したかを知る方法はありません。

于 2009-12-04T20:20:26.623 に答える
0

ユーザーが入力した値の場合。値を文字列として受け入れます。次に、文字列関数を使用して「。」の位置を見つけることができます。次に、文字列の長さからその数値を引いて、探している数値を取得します。もちろん、それを trim() して、実際に入力された数値であることを確認する必要があります..

于 2009-12-04T20:10:15.393 に答える
0

double にこだわっている場合は、文字列に変換し、小数点以下の文字数を数えます。1.99999999998 のような数値を「2」として表示する魔法が関係していると思います

于 2009-12-04T20:09:40.263 に答える
0

BigDecimal に変換します。BigDecimal.scale() = 桁数

于 2012-01-29T17:58:35.313 に答える