Float Question

This is probably the stupidest question ive ever had to ask on any board
so im sorry lol. :-p

Yes i’ve googled and found a solution but i cant believe that the
solution presented is correct or that the great minds behind ruby did
not include something like this.

I want to get a float 2.3333 to display as 2.33 or 2.333 etc.

Now, i read the manual, Numerical, Float, Math sections but could not
find a way to do this. Yes you can use string manipulation but that
just defeats the purpose of having something like this built into the
Float stack.

ex. someFloat = Float.new(2) ==> 2.12
someFloat = Float.new(5) => 2.12345

Any thoughts?

What you’re looking for is sprintf() though I suspect you know that
already from your comment below. Ie:

sprintf( “%0.02f”, 234.2342342)

You deride this as “string manipulation” though in effect as soon as
you display the number that’s what you’re doing, no matter where or
why you want to display it. The number only exists as a true float as
long as you don’t look at it; as soon as you do, you’ve forced it to
achieve stringness.

Makes sense?

Hey Chris thanks for the feedback. Yea im using that but i was looking
for something built into the Float stack. Something along the lines of
Float.new(). Basically something
without the need to use sprintf.

Next release of Ruby request? lol

Or even the current release!

class Float
def truncate(places = 0)
return to_i if places == 0
sprintf( “%0.#{places}f”, self).to_f
end
end

irb(main):007:0> 234.2342342.truncate 2
=> 234.23
irb(main):008:0> 234.2342342.truncate
=> 234

On 1-Dec-07, at 12:30 AM, Armando P. wrote:

Hey Chris thanks for the feedback. Yea im using that but i was
looking for something built into the Float stack. Something along
the lines of Float.new().
Basically something without the need to use sprintf.

In that case the monkey-patch suggestions made by others would do the
trick for you. I personally wouldn’t like to see anything like this in
the Float class proper since it really isn’t part of the float itself
but rather an operation on the string representation of it.

Of the m-p suggestions made (is this question now mp-complete?), I
like Pat M.'s truncate() the best:

On 01.12.2007 09:26, Armando P. wrote:

Hey Chris thanks for the feedback. Yea im using that but i was looking
for something built into the Float stack.

Class != stack.

Something along the lines of
Float.new(). Basically something
without the need to use sprintf.

I fail to see where the issue with using (s)printf is. Anyway, if you
do not like the syntax of sprintf you can as well do this:

irb(main):001:0> f=1.0/3
=> 0.333333333333333
irb(main):002:0> “%.2f” % f
=> “0.33”

Next release of Ruby request? lol

Probably not. As others have demonstrated, you can easily do this in
Ruby today. But it seems, few people know the star operator in printf
format strings. You can do this:

irb(main):021:0> module Precision
irb(main):022:1> def format(decimals,total=0)
irb(main):023:2> sprintf “%*.*f”, total, decimals, self
irb(main):024:2> end
irb(main):025:1> end
=> nil
irb(main):026:0> f=1.0/3
=> 0.333333333333333
irb(main):027:0> f.format 3
=> “0.333”
irb(main):028:0> f.format 3,10
=> " 0.333"

Kind regards

robert

You can monkey patch Float to do this, basically. Whether or not it’s
a good idea is another matter entirely.

class Float
def to_s
#force all Floats to 2 decimal places
“%.2f” % self
end
end

puts 1.2345678 # => 1.23

Or maybe:

class Float
attr_accessor :decimals
alias_method :default_to_s, :to_s
def to_s
decimals ? “%.#{decimals}f” % self : default_to_s
end
end

a = 1.234567
puts a # => 1.234567
a.decimals = 2
puts a # => 1.23

I fail to see where the issue with using (s)printf is.

If i use sprintf im assuming that the argument is changed to a string
type. If then i chose to calculate additional values with this string
type i would have to reconvert it to a float. On the surface its fine,
i wouldnt mind doing it but I need speed and any less lines that ruby
will translate too in terms of machine language is beneficial to me.

I actually like Maddox truncate example. Thanks Maddox. i wasnt aware
of both that feature and *.format Klemme suggested.

On 1-Dec-07, at 2:25 AM, Robert K. wrote:

But it seems, few people know the star operator in printf format
strings. You can do this:

irb(main):021:0> module Precision
irb(main):022:1> def format(decimals,total=0)
irb(main):023:2> sprintf “%*.*f”, total, decimals, self
irb(main):024:2> end
irb(main):025:1> end

You’re right, I didn’t know that one at all and it seems quite handy.
Thanks for the tip.

Armando P. [email protected] wrote:

I actually like Maddox truncate example. Thanks Maddox. i wasnt aware
of both that feature and *.format Klemme suggested.

I’m using that :

def aprox( eps = 1.0e-10 )
( self / eps ).round * eps
end

with :
a_float = 1.2345678901234567890
epss = [ 1.0e-10, 1.0e-8, 1.0e-6, 1.0e-4, 1.0e-2, 1.0, 1.0e2]
epss.each do | eps |
puts “#{a_float}.aprox( #{eps} ) -o-> #{a_float.aprox( eps )}”
end

gives :
1.23456789012346.aprox( 1.0e-10 ) -o-> 1.2345678901
1.23456789012346.aprox( 1.0e-08 ) -o-> 1.23456789
1.23456789012346.aprox( 1.0e-06 ) -o-> 1.234568
1.23456789012346.aprox( 0.0001 ) -o-> 1.2346
1.23456789012346.aprox( 0.01 ) -o-> 1.23
1.23456789012346.aprox( 1.0 ) -o-> 1.0
1.23456789012346.aprox( 100.0 ) -o-> 0.0

I’m also using an aproximate float comparator :
def ===( aFloat, eps = 1.0e-10)
begin
clazz = aFloat.class.to_s
raise “Argument "#{aFloat}" must be a Float (being of
#{clazz}).” if clazz != “Float”
( self > aFloat - eps ) && ( self < aFloat + eps )
rescue
puts “An error occurred: #{$!}”
nil
end
end

with :
vref = 2.0
val = [ 2.00000000002, 2.00000002, 2.00002, 2.002 ]
val.each do | v |
puts “( #{vref} ===? #{v} ) = #{( vref === v )}”
puts “( #{vref} ===? #{v}, 1.0e-8 ) = #{( vref.===(v, 1.0e-8) )}”
puts “( #{vref} ===? #{v}, 1.0e-6 ) = #{( vref.===(v, 1.0e-6) )}”
puts “( #{vref} ===? #{v}, 1.0e-4 ) = #{( vref.===(v, 1.0e-4) )}”
end

gives :
( 2.0 ===? 2.00000000002 ) = true
( 2.0 ===? 2.00000000002, 1.0e-8 ) = true
( 2.0 ===? 2.00000000002, 1.0e-6 ) = true
( 2.0 ===? 2.00000000002, 1.0e-4 ) = true
( 2.0 ===? 2.00000002 ) = false
( 2.0 ===? 2.00000002, 1.0e-8 ) = false
( 2.0 ===? 2.00000002, 1.0e-6 ) = true
( 2.0 ===? 2.00000002, 1.0e-4 ) = true
( 2.0 ===? 2.00002 ) = false
( 2.0 ===? 2.00002, 1.0e-8 ) = false
( 2.0 ===? 2.00002, 1.0e-6 ) = false
( 2.0 ===? 2.00002, 1.0e-4 ) = true
( 2.0 ===? 2.002 ) = false
( 2.0 ===? 2.002, 1.0e-8 ) = false
( 2.0 ===? 2.002, 1.0e-6 ) = false
( 2.0 ===? 2.002, 1.0e-4 ) = false

On Dec 1, 2007, at 12:04 PM, Armando P. wrote:

If i use sprintf im assuming that the argument is changed to a
string type. If then i chose to calculate additional values with
this string type i would have to reconvert it to a float. On the
surface its fine, i wouldnt mind doing it but I need speed and any
less lines that ruby will translate too in terms of machine
language is beneficial to me.

This statement just confused me more. sprintf doesn’t change the
underlying objects–it just creates a string representation of them.
You are free to use the original objects as you like.

It sounds like you aren’t primarily interested in the format of the
string representation of a float but instead would like to compute
a rounded or truncated value. That is a completely different
problem. Pat’s solution included a roundtrip conversion to a
decimal/string representation, which is going to be inaccurate and
expensive. Of course if you want to ‘round’ a float then you’ll
want to round to a power of two to avoid conversion problems.

Maybe BigDecimal objects would work better for you? You could
at least avoid the base2/base10 conversion problems.

Gary W.

On 01.12.2007 17:59, Armando P. wrote:

I fail to see where the issue with using (s)printf is.

If i use sprintf im assuming that the argument is changed to a string
type. If then i chose to calculate additional values with this string
type i would have to reconvert it to a float.

But this is exactly what you asked for. Quoting from your original
posting:

I want to get a float 2.3333 to display as 2.33 or 2.333 etc.

You are clearly asking for a string representation with specific
properties, namely the number of digits after the decimal point.

On the surface its fine,
i wouldnt mind doing it but I need speed and any less lines that ruby
will translate too in terms of machine language is beneficial to me.

Maybe we should start over with you stating what it is that you want to
do.

And please, do not top post.

Regards

robert