Float precision

Hi all,

Is there a direct method to get something like:

var = sprintf("%.2f", 92.22312).to_f

Thanks alot!

Difei

The round function in the float class does not provide a precision
feature, but you can do something like:
(100*9.23234234234532).round/100.0

According to my benchmarks this is at least 1/3 faster than your
approach

Thomas

thomas peklak wrote:

The round function in the float class does not provide a precision
feature, but you can do something like:
(100*9.23234234234532).round/100.0

According to my benchmarks this is at least 1/3 faster than your
approach

Thomas

thanks for the sharing.

thomas peklak wrote:

The round function in the float class does not provide a precision
feature, but you can do something like:
(100*9.23234234234532).round/100.0

According to my benchmarks this is at least 1/3 faster than your
approach

Thomas

Just out of curiosity, does it make any difference on benchmarks with
Ruby using division versus multiplication? It used to be much faster to
multiply by .01 than divide by 100. I don’t know if this has changed
with newer processors and compilers.

thomas peklak wrote:

You are right, multiplying with 0.01 is even fast, see the benchmarks:

Thanks for the information. It looks like multiplication is still twice
as fast as division. I am sure that with today’s computers this only
matters with large numbers of operations but on a IBM PC-1 it made a lot
of difference.

You are right, multiplying with 0.01 is even fast, see the benchmarks:

require ‘benchmark’

times = 1000000
float = 9.234234765765765764
Benchmark.bm do |r|
r.report(‘SPf :’) {
times.times do
f1 = sprintf(’%.2f’ ,float).to_f
end
}
r.report(‘100 :’) {
times.times do
f2 = (100 * float).round/100.0
end
}
r.report(’
.01 :’) {
times.times do
f3 = (100 * float).round*0.01
end
}
end

    user     system      total        real

SPf : 5.590000 0.050000 5.640000 ( 5.720373)
*100 : 3.760000 0.040000 3.800000 ( 3.829771)
*.01 : 1.770000 0.010000 1.780000 ( 1.811917)

Thomas

Robert K. wrote in post #727777:

2008/9/13 thomas peklak [email protected]:

You are right, multiplying with 0.01 is even fast, see the benchmarks:

require ‘benchmark’
user system total real
SPf : 5.590000 0.050000 5.640000 ( 5.720373)
*100 : 3.760000 0.040000 3.800000 ( 3.829771)
*.01 : 1.770000 0.010000 1.780000 ( 1.811917)

It’s even more efficient to calculate with the full precision and
round only on output. :slight_smile:

Cheers

robert

This doesn’t seem to work for certain numbers though… is there a way
to round this 7.17… e+25:

puts “#{cd}\t#{(100 * thr.max).round*0.01}”

output …

1000 7.17897987691824e+25
200 3.35
4000 0.99
20000 0.69

2008/9/13 thomas peklak [email protected]:

You are right, multiplying with 0.01 is even fast, see the benchmarks:

require ‘benchmark’
user system total real
SPf : 5.590000 0.050000 5.640000 ( 5.720373)
*100 : 3.760000 0.040000 3.800000 ( 3.829771)
*.01 : 1.770000 0.010000 1.780000 ( 1.811917)

It’s even more efficient to calculate with the full precision and
round only on output. :slight_smile:

Cheers

robert

Joshua S. wrote in post #995421:

Not surprisingly, it’s extremely quicker to convert to a string and
match a regular expression.

  user     system      total        real

spf : 1.560000 0.000000 1.560000 ( 1.557252)
*100 : 0.320000 0.000000 0.320000 ( 0.322573)
*.01 : 0.350000 0.000000 0.350000 ( 0.343289)
regex: 0.000000 0.000000 0.000000 ( 0.000019)

You should be suspicious of a result which indicates it’s 5 orders of
magnitude faster.

r.report(‘regex:’) {
f4 = float.to_s.match(/(^-?\d+(.\d{1,2})?)/)[1].to_f
}

Ahem, you forgot the “times.times do…end” loop in the benchmark :slight_smile:

Not surprisingly, it’s extremely quicker to convert to a string and
match a regular expression.

  user     system      total        real

spf : 1.560000 0.000000 1.560000 ( 1.557252)
*100 : 0.320000 0.000000 0.320000 ( 0.322573)
*.01 : 0.350000 0.000000 0.350000 ( 0.343289)
regex: 0.000000 0.000000 0.000000 ( 0.000019)

The expression
(^-?\d+(.\d{1,2})?) matches all the following:

12
1.2
1.234567890
12.34567890
123.4567890
1234.567890
-12
-1.2
-1.234567890
-12.34567890
-123.4567890
-1234.567890


require ‘benchmark’

times = 1000000
float = 9.234234765765765764
Benchmark.bm do |r|
r.report(‘spf :’) {
times.times do
f1 = sprintf(’%.2f’ ,float).to_f
end
}
r.report(‘100 :’) {
times.times do
f2 = (100 * float).round/100.0
end
}
r.report(’
.01 :’) {
times.times do
f3 = (100 * float).round*0.01
end
}
r.report(‘regex:’) {
f4 = float.to_s.match(/(^-?\d+(.\d{1,2})?)/)[1].to_f
}
end

Brian C. wrote in post #995481:

Joshua S. wrote in post #995421:

Not surprisingly, it’s extremely quicker to convert to a string and
match a regular expression.

  user     system      total        real

spf : 1.560000 0.000000 1.560000 ( 1.557252)
*100 : 0.320000 0.000000 0.320000 ( 0.322573)
*.01 : 0.350000 0.000000 0.350000 ( 0.343289)
regex: 0.000000 0.000000 0.000000 ( 0.000019)

You should be suspicious of a result which indicates it’s 5 orders of
magnitude faster.

r.report(‘regex:’) {
f4 = float.to_s.match(/(^-?\d+(.\d{1,2})?)/)[1].to_f
}

Ahem, you forgot the “times.times do…end” loop in the benchmark :slight_smile:

Wow. Yea … scratch that.

  user     system      total        real

spf : 1.570000 0.000000 1.570000 ( 1.569649)
*100 : 0.330000 0.000000 0.330000 ( 0.323864)
*.01 : 0.340000 0.000000 0.340000 ( 0.342777)
regex: 4.120000 0.010000 4.130000 ( 4.127264)