i came following convert list[int] => try[bigdecimal]
:
import scala.util.try def f(xs: list[int]): try[bigdecimal] = try { xs.mkstring.toint }.map ( bigdecimal(_) )
example:
scala> f(list(1,2,3,4)) res4: scala.util.try[bigdecimal] = success(1234) scala> f(list(1,2,3,55555)) res5: scala.util.try[bigdecimal] = success(12355555)
is there way write function without resorting string conversion step?
not pretty, , i'm not convinced it's more efficient. here's basic outline.
val pwrs:stream[bigint] = 10 #:: pwrs.map(_ * 10) list(1,2,3,55555).foldleft(0:bigint)((p,i) => pwrs.find(_ > i).get * p + i)
here little more fleshed out error handling.
import scala.util.try def f(xs: list[int]): try[bigdecimal] = try { lazy val pwrs: stream[bigdecimal] = 10 #:: pwrs.map(_ * 10) xs.foldleft(0: bigdecimal) { case (acc, i) if >= 0 => pwrs.find(_ > i).get * acc + case _ => throw new error("bad") } }
update
just giggles, thought i'd plug code rex kerr's handy benchmarking/profiling tool, thyme.
the code
import scala.util.try def fstring(xs: list[int]): try[bigint] = try { bigint(xs.mkstring) } def fstream(xs: list[int]): try[bigint] = try { lazy val pwrs: stream[bigint] = 10 #:: pwrs.map(_ * 10) xs.foldleft(0: bigint) { case (acc, i) if >= 0 => pwrs.find(_ > i).get * acc + case _ => throw new error("bad") } } def flog10(xs: list[int]): try[bigint] = try { xs.foldleft(0: bigint) { case (acc, i) if >= 0 => math.pow(10, math.ceil(math.log10(i))).toint * acc + case _ => throw new error("bad") } }
fstring()
slight simplification of kevin's original question. fstream()
proposed non-string implementation. flog10
same alexey's suggested enhancement.
you'll note i'm using bigint
instead of bigdecimal
. found both non-string methods encountered bug somewhere around 37th digit of result. kind of rounding error or something, there no problem bigint
that's used.
test setup
// create list of 40 ints , check contents val lst = list.fill(40)(util.random.nextint(20000)) lst.min // 5 lst.max // 19858 lst.mkstring.length // 170 val th = ichi.bench.thyme.warmed(verbose = print) th.pbenchwarm(th.warm(fstring(lst)), title="fstring") th.pbenchwarm(th.warm(fstream(lst)), title="fstream") th.pbenchwarm(th.warm(flog10(lst)), title="flog10")
results
benchmark fstring (20 calls in 345.6 ms) time: 4.015 95% ci 3.957 - 4.073 (n=19) garbage: 109.9 ns (n=2 sweeps measured)
benchmark fstream (20 calls in 305.6 ms) time: 7.118 95% ci 7.024 - 7.213 (n=19) garbage: 293.0 ns (n=3 sweeps measured)
benchmark flog10 (20 calls in 382.8 ms) time: 9.205 95% ci 9.187 - 9.222 (n=17) garbage: 73.24 ns (n=2 sweeps measured)
so right efficiency of non-string algorithm. oddly, using math._
avoid stream
creation doesn't appear better. didn't expect that.
takeaway
number-to-string , string-to-number transitions reasonably efficient.
Comments
Post a Comment