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
}