How to get ruby to show more decimal places? - ruby

I'm currently doing a project Euler problem that requires me to find patterns in repeating decimals. However, Ruby rounds too soon and I can't find a way to flesh out decimals to the nth place.
For instance:
1/7.to_f => 0.14285714285714285
but I'm trying to make it so:
1/7.to_f => 0.14285714285714285714285714285757142857142857
Any help would be greatly appreciated!

All languages support being able to define the precision of floating point in output. Ruby uses the common format strings:
pi = 355.0/113.0
'%1.5f' % pi # => "3.14159"
Or, in your case:
'%1.20f' % (1.0/7.0) # => "0.14285714285714284921"
'%1.20f' % (1.to_f/7) # => "0.14285714285714284921"
'%1.20f' % (1/7.to_f) # => "0.14285714285714284921"
I'd recommend reading the documentation for String's % and Kernel::sprintf. How Ruby determines to use fixed or floating math and the uses of to_f is covered in any decent Ruby tutorial.

You can easily get as many repeating digits as you like, by scaling up the computation by a power of 10
10**100/7
=> 1428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428571428

Related

How do I use string formatter to restrain two digits before decimal point and two digits after in Ruby?

I'm well aware that if you want to force two digits, you do
"%2d" % blah
And if in a scenario that it is necessary to enforce two digits after decimal point, you do
".2f" % blah
I'm a bit confused on what should I do in order to combine those two together? Which is to say, 4.6 will be rendered as 04.60, and 34.274 will still be rendered as 34.27.
Apparently
"%2d.2f" % blah
doesn't work.
I'm thinking that I should probably go for
"%2d%.2f" % [bla_first_half, blah_second_half]
but I'm kind of reluctant to do so since it's a bit tedious.
I know if Java one can easily do
"##.##"
So is there any ruby counterpart like that? Cheers!
"%05.2f" % 4.66 # => 04.66
"%05.2f" % 34.274 # => 34.27
.2f means the float will be rounded to only two digits after the .
05 means the string will be no less than 5 characters and if there are less - it will fill the missing ones with 0.

Strange result for Float

1.824999999999999.round(2)
# => 1.82
1.82499999999999999.round(2)
# => 1.83
I don't understand why the result in the first case is 1.82 and for the latter 1.83. My desired result is 1.82 for both cases.
As is well known, a floating number in computer has errors. Notice that both numbers that you have are close to 1.825. In your first case, the number is small enough to be differentiated from 1.825.
1.824999999999999
# => 1.824999999999999
In your second case, having enough 9s makes the value close enough to be considered exactly as 1.825:
1.82499999999999999
# => 1.825
Then, when you apply round, you get 1.83.
In addition to the many excellent explanations here, I'd like to give an example using BigDecimal
o = BigDecimal.new('1.82499999999999999', 17)
2.0.0p247 :011 > o.round(2).to_f
=> 1.82
Also notice that #round takes various modes for rounding, as per the docs.
Ref:
http://www.ruby-doc.org/stdlib-2.1.0/libdoc/bigdecimal/rdoc/BigDecimal.html#method-c-mode
http://www.ruby-doc.org/stdlib-2.1.0/libdoc/bigdecimal/rdoc/BigDecimal.html#method-i-round
After a certain number of (binary) digits, Ruby cannot represent differences between Float literals, even if you've entered the value directly in source code or the console
1.82499999999999999 == 1.825
# => true
If you really need a high level of precision, then you could look at the BigDecimal class. Although you could still enter enough 9s to reach limits in that class.
Floats are notoriously imprecise as sawa and Neil have pointed out.
If this is mainly an issue for testing, you can use assert_in_delta if you're using minitest, or be_within with rSpec

Floats, Decimals, or Integers

I have a rails app that process some data, and some of these data include numbers with decimals such as 1.9943, and division between these numbers and other integers. I wanted to know what the best way to store this was.
I thought of storing the numbers that would retain integers as integers and numbers that could become decimals as decimals. Although it was in a weird format like
#<BigDecimal:7fda470aa9f0,'0.197757E1',18(18)>
it seems to perform the correct arithmetic when I divide two decimal numbers or a decimal with an integer. When I try to divide integers with integers, it doesn't work correctly. I thought rails would automatically convert the result into a proper decimal, but it seems to keep it as integer and strip the remainders. Is there anything I can do about this?
And what would be the best way to store this type of information? Should I store it all as decimals, or maybe floats?
If you want to divide two integers without losing precision, you need to cast one of them to a Float or BigDecimal first:
irb(main):007:0> 2/3
=> 0
irb(main):008:0> Float(2)/3
=> 0.666666666666667
I am a bit confused when you say that you get different results when you divide a Float/Integer vs. Integer/Float? These should have the same result:
irb(main):010:0> Integer(2)/Float(3)
=> 0.666666666666667
irb(main):011:0> Float(2)/Integer(3)
=> 0.666666666666667
irb(main):012:0> String( BigDecimal('2')/3 )
=> "0.666666666666666666666666666666666666666666666666666667E0"
irb(main):013:0> String( 2/BigDecimal('3') )
=> "0.666666666666666666666666666666666666666666666666666667E0"
Can you provide a code example?
As far as storage goes, any integer data should be stored as an Integer regardless of its expected use in future calculations.
Storing Floats vs. BigDecimals depends on how much precision you require. If you don't require much precision, a Float will provide a double-precision representation. If you require a high degree of precision, BigDecimal will provide an arbitrary-precision representation.
Related: Ruby Numbers - Explains the difference between Integers, Floats, BigDecimals, and Rationals
you don't need big precision to have problems with floats
You should better avoid as much as possible floats.
Ex: 123.6 - 123 => in floats it will give you 0,59..
in BigDecimal you will have 0.6

ruby: converting from float to integer in ruby produces strange results

ree-1.8.7-2010.02 :003 > (10015.8*100.0).to_i
=> 1001579
ree-1.8.7-2010.02 :004 > 10015.8*100.0
=> 1001580.0
ree-1.8.7-2010.02 :005 > 1001580.0.to_i
=> 1001580
ruby 1.8.7 produces the same.
Does anybody knows how to eradicate this heresy? =)
Actually, all of this make sense.
Because 0.8 cannot be represented exactly by any series of 1 / 2 ** x for various x, it must be represented approximately, and it happens that this is slightly less than 10015.8.
So, when you just print it, it is rounded reasonably.
When you convert it to an integer without adding 0.5, it truncates .79999999... to .7
When you type in 10001580.0, well, that has an exact representation in all formats, including float and double. So you don't see the truncation of a value ever so slightly less than the next integral step.
Floating point is not inaccurate, it just has limitations on what can be represented. Yes, FP is perfectly accurate but cannot necessarily represent every number we can easily type in using base 10. (Update/clarification: well, ironically, it can represent exactly every integer, because every integer has a 2 ** x composition, but "every fraction" is another story. Only certain decimal fractions can be exactly composed using a 1/2**x series.)
In fact, JavaScript implementations use floating point storage and arithmetic for all numeric values. This is because FP hardware produces exact results for integers, so this got the JS guys 52-bit math using existing hardware on (at the time) almost-entirely 32-bit machines.
Due to truncation error in float calculation, 10015.8*100.0 is actually calculated as 1001579.999999... So if you simply apply to_i, it cuts off the decimal part and returns 1001579
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
>> sprintf("%.16f", 10015.8*100.0)
=> "1001579.9999999999000000"
And Float#to_i truncates this to 1001579.

Handling Massive (high precision) Floats in Ruby

I'm making an application which is listening to prices being updated regularly, but occasionally my data source throws me something like "1.79769313486232e+308". The numbers that get sent will never by really big numbers (eg. "179769313486232e+308"), but as with the example above, they come with a lot of precision.
I'd be happy to drop everything after the first couple of decimal places, and end up with something like "1.798", but the following code isn't working for me:
irb(main):001:0> s = '1.79769313486232e+308'
=> "1.79769313486232e+308"
irb(main):002:0> ("%.3f" % s).to_f
(irb):2: warning: Float 1.79769313486232e+30... out of range
=> 0.0
Any graceful ways to handle these kind of numbers in Ruby?
You need to find out from your data source what those really big numbers mean. The price isn't actually 1.797e+308, but it probably also isn't 1.797. How you deal with those numbers depends entirely on what value you should be interpreting them as.
Update: I'm not sure you understand what this number means. 1.79769313486232e+308 is 1.79769313486232 times ten to the 308th power. It's a number with more than 300 digits to the left of the decimal point. This isn't a price, it's a mistake. It's the upper limit of what double-precision floating point can represent.
In other words, you're getting the equivalent of 0xFFFFFFFF or something like that, but interpreted as a floating point number.
That's right at the top of the range of "doubles". In Python for example it's converted to the special float called "inf".
The graceful way to handle this one might be to treat it as infinity
you could strip out extra decimals using regexp
>> s =~ /\.\d\d\d(\d+)/
>> s.gsub($1, '')
=> "1.797e+308"

Resources