Any idea why this calculates the integer the way it does? irb> ("291.15".to_f * 100.0).to_i => 29114 Thanks, Tom -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-23 03:41 UTC
Re: Weird issue with converting floats to integer
TomRossi7 wrote in post #970207:> Any idea why this calculates the integer the way it does? > > irb> ("291.15".to_f * 100.0).to_i > => 29114Because of the vagaries of floating-point arithmetic: irb> ("291.15".to_f * 100.0) < 29115 => true irb> printf "%.30f", ("291.15".to_f * 100.0) 29114.999999999996362021192908287048 It bears repeating: never, ever use Floats for arithmetic. If you can''t use fixed-point math, then use BigDecimal.> > Thanks, > TomBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Or just change the way you calculate to get at the level of accuracy that you want/need: irb> ("291.15".to_f * 1000.0).to_i/10 => 29115 Jeff On Dec 22, 7:41 pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> TomRossi7 wrote in post #970207: > > > Any idea why this calculates the integer the way it does? > > > irb> ("291.15".to_f * 100.0).to_i > > => 29114 > > Because of the vagaries of floating-point arithmetic: > irb> ("291.15".to_f * 100.0) < 29115 > => true > irb> printf "%.30f", ("291.15".to_f * 100.0) > 29114.999999999996362021192908287048 > > It bears repeating: never, ever use Floats for arithmetic. If you can''t > use fixed-point math, then use BigDecimal. > > > > > Thanks, > > Tom > > Best, > -- > Marnen Laibow-Koserhttp://www.marnen.org > mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > > -- > Posted viahttp://www.ruby-forum.com/.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-23 17:51 UTC
Re: Weird issue with converting floats to integer
Please quote when replying. Jeff Burlysystems wrote in post #970344:> Or just change the way you calculate to get at the level of accuracy > that you want/need: > > irb> ("291.15".to_f * 1000.0).to_i/10 > => 29115That''s incredibly silly IMHO. Besides, it will not always be the same for all values, will it? I think BigDecimal is the right answer here.> > JeffBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
I have currency information that I plan to store as an integer -- ironically to avoid issues like this. The user input will always be in a decimal form. I''m thinking I will just do this (''291.15''.to_f * 100).round instead. That should round out any of the weird float issues. On Dec 23, 12:51 pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Please quote when replying. > > Jeff Burlysystems wrote in post #970344: > > > Or just change the way you calculate to get at the level of accuracy > > that you want/need: > > > irb> ("291.15".to_f * 1000.0).to_i/10 > > => 29115 > > That''s incredibly silly IMHO. Besides, it will not always be the same > for all values, will it? I think BigDecimal is the right answer here. > > > > > Jeff > > Best, > -- > Marnen Laibow-Koserhttp://www.marnen.org > mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > > -- > Posted viahttp://www.ruby-forum.com/.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-23 18:12 UTC
Re: Weird issue with converting floats to integer
Please quote when replying. TomRossi7 wrote in post #970346:> I have currency information that I plan to store as an integer -- > ironically to avoid issues like this. The user input will always be > in a decimal form. I''m thinking I will just do this (''291.15''.to_f * > 100).round instead. That should round out any of the weird float > issues.I think there are better ways of doing that -- such as using a DECIMAL field in the database. Then no conversion is necessary and the data is stored as fixed-point. Or, if you''d rather store the data as an integral number of pennies (though that may have i18n issues -- there are a few currencies, such as the Kuwaiti dinar, that are subdivided into 1000, not 100), then a quick way would be to normalize the string so that it contains 2 decimal places (so "123" would become "123.00"), then drop the decimal point. Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Dec 22, 10:34 pm, TomRossi7 <t...-5bxIUPmzHicFraO2wh7vUA@public.gmane.org> wrote:> Any idea why this calculates the integer the way it does? > > irb> ("291.15".to_f * 100.0).to_i > => 29114As Marnen''s already pointed out, the issue is that the result is a *tiny* bit smaller than 29115, so to_i truncates off the entire fractional part and gives the wrong answer. In general, if you want to convert a decimal to an integer the way most people would on paper, use .round.to_i, which will correctly round the float to the nearest integer. On the currency issue, it''s typically a good idea to avoid floating- point throughout the process if you''re trying to get a reliable fixed- point result. Decimal columns are definitely a good idea for this sort of thing. --Matt Jones -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2010-Dec-23 21:14 UTC
Re: Weird issue with converting floats to integer
TomRossi7 wrote in post #970346:> I have currency information that I plan to store as an integer -- > ironically to avoid issues like this. The user input will always be > in a decimal form. I''m thinking I will just do this (''291.15''.to_f * > 100).round instead. That should round out any of the weird float > issues.As was said before by others in this thread, using the BigDecimal type really is the most reliable, and simple, solution. Don''t reinvent the wheel with calculating in pennies and rounding etc. ... In the migration, do this: class AddAmountToPayment < ActiveRecord::Migration def self.up add_column :payments, :amount, :decimal, :precision => 12, :scale => 2 end ... This which will work automatically correct when reading user input in your forms and when doing internal calculations: $ rails c Loading development environment (Rails 3.0.3) 001:0> Payment.columns.select{|c| c.sql_type =~ /decimal/} => [#<ActiveRecord::ConnectionAdapters::MysqlColumn:0xb6c1e844 @sql_type="decimal(12,2)", @scale=2, @name="amount", @limit=12, @precision=12, @primary=false, @type=:decimal, @default=nil, @null=true>] 002:0> payment = Payment.new(:amount => "291.15") => #<Payment id: nil, user_id: nil, testing: nil, created_at: nil, updated_at: nil, amount: #<BigDecimal:b6c09318,''0.29115E3'',8(12)>> 003:0> payment.amount => #<BigDecimal:b6c07e14,''0.29115E3'',8(12)> 004:0> payment.amount.to_s => "291.15" ... 019:0> (payment.amount - BigDecimal("291") - BigDecimal("0.15")).to_s => "0.0" 020:0> ((291.15 - 291) - 0.15).to_s => "-2.27318164292001e-14" # Rounding errors with float !!! HTH, Peter -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 23 December 2010 03:41, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> TomRossi7 wrote in post #970207: >> Any idea why this calculates the integer the way it does? >> >> irb> ("291.15".to_f * 100.0).to_i >> => 29114 > > Because of the vagaries of floating-point arithmetic: > irb> ("291.15".to_f * 100.0) < 29115 > => true > irb> printf "%.30f", ("291.15".to_f * 100.0) > 29114.999999999996362021192908287048 > > It bears repeating: never, ever use Floats for arithmetic. If you can''t > use fixed-point math, then use BigDecimal.I have to disagree here. I would rephrase it as _almost_ never use Floats The one time when they would be appropriate is if you have a large amount of arithmetic to perform. The sort of thing that might occur in complex statistical analysis for example or engineering calculations of some sort. On most (possibly all) computers floating point consumes vastly less processor time to perform than BigDecimal. This is a rare occurence in Rails apps I expect so I agree that for most people Marnen''s advice would be appropriate. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-23 21:34 UTC
Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970376:> On 23 December 2010 03:41, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >> 29114.999999999996362021192908287048 >> >> It bears repeating: never, ever use Floats for arithmetic. If you can''t >> use fixed-point math, then use BigDecimal. > > I have to disagree here.I knew someone would. :)> I would rephrase it as _almost_ never use > Floats The one time when they would be appropriate is if you have a > large amount of arithmetic to perform. The sort of thing that might > occur in complex statistical analysis for example or engineering > calculations of some sort. On most (possibly all) computers floating > point consumes vastly less processor time to perform than BigDecimal.Then use fixed-point math. IEEE floats are 100% inappropriate for any sort of mathematical calculation. And who cares how fast they are if they''re inaccurate? Inaccurate engineering calculations are worse than none at all -- do *you* want to drive over that bridge? :) If you want to use IEEE floats for arithmetic, then the onus is on you to do the requisite numerical analysis to figure out how much error you are introducing, and to inform your users of that fact.> This is a rare occurence in Rails appsYes indeed!> I expect so I agree that for > most people Marnen''s advice would be appropriate. > > ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 23 December 2010 21:34, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Colin Law wrote in post #970376: >> On 23 December 2010 03:41, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >> wrote: >>> 29114.999999999996362021192908287048 >>> >>> It bears repeating: never, ever use Floats for arithmetic. If you can''t >>> use fixed-point math, then use BigDecimal. >> >> I have to disagree here. > > I knew someone would. :)You probably guessed it might be me :)> >> I would rephrase it as _almost_ never use >> Floats The one time when they would be appropriate is if you have a >> large amount of arithmetic to perform. The sort of thing that might >> occur in complex statistical analysis for example or engineering >> calculations of some sort. On most (possibly all) computers floating >> point consumes vastly less processor time to perform than BigDecimal. > > Then use fixed-point math. IEEE floats are 100% inappropriate for any > sort of mathematical calculation. And who cares how fast they are if > they''re inaccurate? Inaccurate engineering calculations are worse than > none at all -- do *you* want to drive over that bridge? :)We are getting off topic for Rails apps but I think if you looked into most engineering and scientific software you would find they use floating point arithmetic. Fixed point is not appropriate as intermediate calculations need guaranteed _relative_ error, not absolute error. That is what floats provide.> If you want to use IEEE floats for arithmetic, then the onus is on you > to do the requisite numerical analysis to figure out how much error you > are introducing, and to inform your users of that fact.Yes of course. As you said, the bridge designer needs to know the possible errors in his calculations. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser wrote in post #970377:> Then use fixed-point math. IEEE floats are 100% inappropriate for any > sort of mathematical calculation. And who cares how fast they are if > they''re inaccurate? Inaccurate engineering calculations are worse than > none at all -- do *you* want to drive over that bridge? :)Let''s break this down to a comparison of accuracy vs. precision. Take for example the value 1/3. First using floating point math: x = 1.0 => 1.0 y = 3.0 => 3.0 z = x / y => 0.3333333333333333 Now with Ruby''s BigDecimal math: x = BigDecimal.new(''1'') => #<BigDecimal:102c078,''0.1E1'',4(8)> y = BigDecimal.new(''3'') => #<BigDecimal:10388f0,''0.3E1'',4(8)> z = x / y => #<BigDecimal:103680c,''0.33333333E0'',8(16)> In the case of float we have 16 decimal digits of precision, but in the case of BigDecimal we have only eight digits of precision. Yes, in the case of BigDecimal we have a value representing "precisely" the value 0.33333333, but that result is obviously less accurate than the result of the floating point calculation. Over large aggregations this can make a difference. It is certainly the case that IEEE floats introduce error due to the inherent storage limitations, but doing precise mathematics as fixed point has it''s own complications as well. Ruby''s BigDecimal class does not provide the needed accuracy for complex mathematics. The difference is that BigDecimal always stores precise values within the limits of it storage space. Where floats store imprecise representations, but representations with a fixed precision. I don''t think either of these classes are appropriate for the sort of math mentioned above. But, they both have their uses. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-24 03:59 UTC
Re: Re: Weird issue with converting floats to integer
Robert Walker wrote in post #970390:> Marnen Laibow-Koser wrote in post #970377: >> Then use fixed-point math. IEEE floats are 100% inappropriate for any >> sort of mathematical calculation. And who cares how fast they are if >> they''re inaccurate? Inaccurate engineering calculations are worse than >> none at all -- do *you* want to drive over that bridge? :) > > Let''s break this down to a comparison of accuracy vs. precision. > > Take for example the value 1/3. > > First using floating point math: > > x = 1.0 > => 1.0 > y = 3.0 > => 3.0 > z = x / y > => 0.3333333333333333 > > Now with Ruby''s BigDecimal math: > x = BigDecimal.new(''1'') > => #<BigDecimal:102c078,''0.1E1'',4(8)> > y = BigDecimal.new(''3'') > => #<BigDecimal:10388f0,''0.3E1'',4(8)> > z = x / y > => #<BigDecimal:103680c,''0.33333333E0'',8(16)> > > In the case of float we have 16 decimal digits of precision, but in the > case of BigDecimal we have only eight digits of precision.Are you sure? Or are only eight digits displayed?> > Yes, in the case of BigDecimal we have a value representing "precisely" > the value 0.33333333, but that result is obviously less accurate than > the result of the floating point calculation.Not obvious at all, since I don''t know how many 3s the BigDecimal is *actually* storing.> > Over large aggregations this can make a difference.Yes, it certainly can.> It is certainly the > case that IEEE floats introduce error due to the inherent storage > limitations, but doing precise mathematics as fixed point has it''s own > complications as well.Sure. BigDecimal is the best of both worlds.> > Ruby''s BigDecimal class does not provide the needed accuracy for complex > mathematics.Of course it does. Why do you think it does not? Anyway, if you need more than BigDecimal, then start climbing into the realms of symbolic math with Rational.> The difference is that BigDecimal always stores precise > values within the limits of it storage space. Where floats store > imprecise representations, but representations with a fixed precision. > > I don''t think either of these classes are appropriate for the sort of > math mentioned above.Why is BigDecimal inappropriate? What would you use instead?> But, they both have their uses.I''m not sure Float has a proper use case at all. :) Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 24 December 2010 03:59, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Robert Walker wrote in post #970390: >> Marnen Laibow-Koser wrote in post #970377: >>> Then use fixed-point math. IEEE floats are 100% inappropriate for any >>> sort of mathematical calculation. And who cares how fast they are if >>> they''re inaccurate? Inaccurate engineering calculations are worse than >>> none at all -- do *you* want to drive over that bridge? :) >> >> Let''s break this down to a comparison of accuracy vs. precision. >> >> Take for example the value 1/3. >> >> First using floating point math: >> >> x = 1.0 >> => 1.0 >> y = 3.0 >> => 3.0 >> z = x / y >> => 0.3333333333333333 >> >> Now with Ruby''s BigDecimal math: >> x = BigDecimal.new(''1'') >> => #<BigDecimal:102c078,''0.1E1'',4(8)> >> y = BigDecimal.new(''3'') >> => #<BigDecimal:10388f0,''0.3E1'',4(8)> >> z = x / y >> => #<BigDecimal:103680c,''0.33333333E0'',8(16)> >> >> In the case of float we have 16 decimal digits of precision, but in the >> case of BigDecimal we have only eight digits of precision. > > Are you sure? Or are only eight digits displayed?$ rails console Loading development environment (Rails 3.0.3) ruby-1.9.2-p0 > x=BigDecimal(''1'')/BigDecimal(''3'') => #<BigDecimal:ad823a4,''0.33333333E0'',8(16)> ruby-1.9.2-p0 > x*BigDecimal(''3'') => #<BigDecimal:ad2b270,''0.99999999E0'',8(20)> ruby-1.9.2-p0 > x*BigDecimal(''3'') == 1 => false ruby-1.9.2-p0 > x*BigDecimal(''3'') - 1 => #<BigDecimal:aa4fdf8,''-0.1E-7'',4(20)> Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 24 December 2010 03:59, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> [...] > I''m not sure Float has a proper use case at all. :)Consider table containing the masses of objects. Columns description and mass (kg), with the following records apple, 0.2 earth, 5.9742E24 sun, 1.98892E30 super massive black hole, 1.0E39 What column type would be appropriate for storing the mass? Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-24 14:21 UTC
Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970449:> On 24 December 2010 03:59, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >> [...] >> I''m not sure Float has a proper use case at all. :) > > Consider table containing the masses of objects. Columns description > and mass (kg), with the following records > apple, 0.2 > earth, 5.9742E24 > sun, 1.98892E30 > super massive black hole, 1.0E39 > > What column type would be appropriate for storing the mass?Irrelevant. If I understand you correctly, you''re asking about DB column types, not Ruby column types. Anyway, the answer is: it depends. If I didn''t need arbitrary precision, I''d store them as floats in the DB, and then change to BigDecimal before doing any math on them. If I did need arbitrary precision, and the DB didn''t provide a BigDecimal-like type, I''d store them as strings.> > ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-24 14:25 UTC
Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970447:> On 24 December 2010 03:59, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >>> >>> x = BigDecimal.new(''1'') >>> => #<BigDecimal:102c078,''0.1E1'',4(8)> >>> y = BigDecimal.new(''3'') >>> => #<BigDecimal:10388f0,''0.3E1'',4(8)> >>> z = x / y >>> => #<BigDecimal:103680c,''0.33333333E0'',8(16)> >>> >>> In the case of float we have 16 decimal digits of precision, but in the >>> case of BigDecimal we have only eight digits of precision. >> >> Are you sure? Or are only eight digits displayed? > > $ rails console > Loading development environment (Rails 3.0.3) > ruby-1.9.2-p0 > x=BigDecimal(''1'')/BigDecimal(''3'') > => #<BigDecimal:ad823a4,''0.33333333E0'',8(16)> > ruby-1.9.2-p0 > x*BigDecimal(''3'') > => #<BigDecimal:ad2b270,''0.99999999E0'',8(20)> > ruby-1.9.2-p0 > x*BigDecimal(''3'') == 1 > => false > ruby-1.9.2-p0 > x*BigDecimal(''3'') - 1 > => #<BigDecimal:aa4fdf8,''-0.1E-7'',4(20)> >Interesting. However, the BigDecimal constructor allows specification of the minimum number of significant figures, so in this case we could have done BigDecimal.new(''1'', 16).> ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Colin Law
2010-Dec-24 14:33 UTC
Re: Re: Re: Re: Weird issue with converting floats to integer
On 24 December 2010 14:25, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Colin Law wrote in post #970447: >> On 24 December 2010 03:59, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >> wrote: >>>> >>>> x = BigDecimal.new(''1'') >>>> => #<BigDecimal:102c078,''0.1E1'',4(8)> >>>> y = BigDecimal.new(''3'') >>>> => #<BigDecimal:10388f0,''0.3E1'',4(8)> >>>> z = x / y >>>> => #<BigDecimal:103680c,''0.33333333E0'',8(16)> >>>> >>>> In the case of float we have 16 decimal digits of precision, but in the >>>> case of BigDecimal we have only eight digits of precision. >>> >>> Are you sure? Or are only eight digits displayed? >> >> $ rails console >> Loading development environment (Rails 3.0.3) >> ruby-1.9.2-p0 > x=BigDecimal(''1'')/BigDecimal(''3'') >> => #<BigDecimal:ad823a4,''0.33333333E0'',8(16)> >> ruby-1.9.2-p0 > x*BigDecimal(''3'') >> => #<BigDecimal:ad2b270,''0.99999999E0'',8(20)> >> ruby-1.9.2-p0 > x*BigDecimal(''3'') == 1 >> => false >> ruby-1.9.2-p0 > x*BigDecimal(''3'') - 1 >> => #<BigDecimal:aa4fdf8,''-0.1E-7'',4(20)> >> > > > Interesting. However, the BigDecimal constructor allows specification > of the minimum number of significant figures, so in this case we could > have done BigDecimal.new(''1'', 16).ruby-1.9.2-p0 > x = BigDecimal.new(''1'', 16)/BigDecimal.new(''3'',16) => #<BigDecimal:a146bbc,''0.33333333E0'',8(16)> ruby-1.9.2-p0 > x*BigDecimal(''3'',16) - 1 => #<BigDecimal:a114acc,''-0.1E-7'',4(20)> It doesn''t make any difference how many digits you have, 1/3 as a decimal number multiplied by 3 will never be equal to 1. I am not sure why the above still gives only 8 digits accuracy however, I would have thought it aught to be 16. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Dec 24, 2:21 pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Colin Law wrote in post #970449:> > If I did need arbitrary precision, and the DB didn''t provide a > BigDecimal-like type, I''d store them as strings.Which still doesn''t allow you to store all numbers with arbitrary precision (in fact putting my mathematical hat on, most numbers can''t be stored like this). You''ll have to deal with numerical error eventually Fred> > > > > Colin > > Best, > -- > Marnen Laibow-Koserhttp://www.marnen.org > mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > > Sent from my iPhone > > -- > Posted viahttp://www.ruby-forum.com/.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-24 14:40 UTC
Re: Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970496:> On 24 December 2010 14:25, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >>>>> >>> => #<BigDecimal:ad2b270,''0.99999999E0'',8(20)> >>> ruby-1.9.2-p0 > x*BigDecimal(''3'') == 1 >>> => false >>> ruby-1.9.2-p0 > x*BigDecimal(''3'') - 1 >>> => #<BigDecimal:aa4fdf8,''-0.1E-7'',4(20)> >>> >> >> >> Interesting. However, the BigDecimal constructor allows specification >> of the minimum number of significant figures, so in this case we could >> have done BigDecimal.new(''1'', 16). > > ruby-1.9.2-p0 > x = BigDecimal.new(''1'', 16)/BigDecimal.new(''3'',16) > => #<BigDecimal:a146bbc,''0.33333333E0'',8(16)> > ruby-1.9.2-p0 > x*BigDecimal(''3'',16) - 1 > => #<BigDecimal:a114acc,''-0.1E-7'',4(20)> > > It doesn''t make any difference how many digits you have, 1/3 as a > decimal number multiplied by 3 will never be equal to 1.I''m aware of that, of course. In this particular case, we could use a Rational to fix that. But that won''t necessarily work with arbitrary floating-point numbers... ...unless we recast them as Rationals and do all math that way. Hmm.> > I am not sure why the above still gives only 8 digits accuracy > however, I would have thought it aught to be 16.Yeah, that''s peculiar. I''ll have to run some tests. (I can almost guarantee that Rubinius would get that one right, since I wrote most of the BigDecimal library at one time. Don''t know if they''re still using it.)> > ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Dec 24, 2:39 pm, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Dec 24, 2:21 pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Which still doesn''t allow you to store all numbers with arbitrary > precision (in fact putting my mathematical hat on, most numbers can''t > be stored like this). You''ll have to deal with numerical error > eventuallyTalking slight bollocks. I meant that you can''t store with infinite precision, ie you''ll always be liable for some error. Fred> > Fred > > > > > > > > Colin > > > Best, > > -- > > Marnen Laibow-Koserhttp://www.marnen.org > > mar...-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > > > Sent from my iPhone > > > -- > > Posted viahttp://www.ruby-forum.com/.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-24 14:47 UTC
Re: Weird issue with converting floats to integer
Frederick Cheung wrote in post #970500:> On Dec 24, 2:39pm, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: >> On Dec 24, 2:21pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: > >> Which still doesn''t allow you to store all numbers with arbitrary >> precision (in fact putting my mathematical hat on, most numbers can''t >> be stored like this). You''ll have to deal with numerical error >> eventually > > Talking slight bollocks. I meant that you can''t store with infinite > precision, ie you''ll always be liable for some error.Of course. You know a better way? Should we just store everything as Rational?> > FredBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Dec 24, 2:47 pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Frederick Cheung wrote in post #970500: > > > On Dec 24, 2:39pm, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > wrote: > >> On Dec 24, 2:21pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: > > >> Which still doesn''t allow you to store all numbers with arbitrary > >> precision (in fact putting my mathematical hat on, most numbers can''t > >> be stored like this). You''ll have to deal with numerical error > >> eventually > > > Talking slight bollocks. I meant that you can''t store with infinite > > precision, ie you''ll always be liable for some error. > > Of course. You know a better way? Should we just store everything as > Rational? >Well that wouldn''t solve things anyway. Just didn''t wanted to make sure no one was under the illusion that there''s some sort of silver bullet for this Fred>-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 24 December 2010 14:47, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Frederick Cheung wrote in post #970500: >> On Dec 24, 2:39pm, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> >> wrote: >>> On Dec 24, 2:21pm, Marnen Laibow-Koser <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote: >> >>> Which still doesn''t allow you to store all numbers with arbitrary >>> precision (in fact putting my mathematical hat on, most numbers can''t >>> be stored like this). You''ll have to deal with numerical error >>> eventually >> >> Talking slight bollocks. I meant that you can''t store with infinite >> precision, ie you''ll always be liable for some error. > > Of course. You know a better way? Should we just store everything as > Rational?For things that _are_ decimal numbers (such as money) use Fixed or BigDecimal and for things that are not decimal then use Float and determine the errors if it is important. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-24 16:36 UTC
Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970510:> On 24 December 2010 14:47, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >>> Talking slight bollocks. I meant that you can''t store with infinite >>> precision, ie you''ll always be liable for some error. >> >> Of course. You know a better way? Should we just store everything as >> Rational? > > For things that _are_ decimal numbers (such as money) use Fixed or > BigDecimal and for things that are not decimal then use Float and > determine the errors if it is important.That''s basically what I''ve been saying, except for "decimal" substitute "rational". However, there''s not always an a priori way to determine if a given field will need to store irrational numbers.> > ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 24 December 2010 16:36, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Colin Law wrote in post #970510: >> On 24 December 2010 14:47, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >> wrote: >>>> Talking slight bollocks. I meant that you can''t store with infinite >>>> precision, ie you''ll always be liable for some error. >>> >>> Of course. You know a better way? Should we just store everything as >>> Rational? >> >> For things that _are_ decimal numbers (such as money) use Fixed or >> BigDecimal and for things that are not decimal then use Float and >> determine the errors if it is important. > > That''s basically what I''ve been saying, except for "decimal" substitute > "rational". However, there''s not always an a priori way to determine if > a given field will need to store irrational numbers.I am not quite sure that is that is the same as "never, ever use Floats for arithmetic" :) Also as we have seen for rational numbers like 1/3 BigDecimal is no better than float, except that it is possible to specify a smaller or larger precision than that which float supplies, and it is a decimal precision rather than a binary one. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-24 17:29 UTC
Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970523:> On 24 December 2010 16:36, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >>> BigDecimal and for things that are not decimal then use Float and >>> determine the errors if it is important. >> >> That''s basically what I''ve been saying, except for "decimal" substitute >> "rational". However, there''s not always an a priori way to determine if >> a given field will need to store irrational numbers. > > I am not quite sure that is that is the same as "never, ever use > Floats for arithmetic" :)Oh, now I see the difference. Even if I store something as a Float, I''d probably use BigDecimal for arithmetic. I simply don''t believe that Float arithmetic has any place at all in a wise programmer''s repertoire. Consider it the 21st-century goto, if you like. :)> > Also as we have seen for rational numbers like 1/3 BigDecimal is no > better than float, except that it is possible to specify a smaller or > larger precision than that which float supplies,That makes it better than Float right there. Also, you don''t accumulate any *more* error.> and it is a decimal > precision rather than a binary one....which is not generally better or worse.> > ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Colin Law
2010-Dec-24 20:56 UTC
Re: Re: Re: Re: Weird issue with converting floats to integer
On 24 December 2010 17:29, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Colin Law wrote in post #970523: >> On 24 December 2010 16:36, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >> wrote: >>>> BigDecimal and for things that are not decimal then use Float and >>>> determine the errors if it is important. >>> >>> That''s basically what I''ve been saying, except for "decimal" substitute >>> "rational". However, there''s not always an a priori way to determine if >>> a given field will need to store irrational numbers. >> >> I am not quite sure that is that is the same as "never, ever use >> Floats for arithmetic" :) > > Oh, now I see the difference. Even if I store something as a Float, I''d > probably use BigDecimal for arithmetic. I simply don''t believe that > Float arithmetic has any place at all in a wise programmer''s repertoire. > Consider it the 21st-century goto, if you like. :) > >> >> Also as we have seen for rational numbers like 1/3 BigDecimal is no >> better than float, except that it is possible to specify a smaller or >> larger precision than that which float supplies, > > That makes it better than Float right there. Also, you don''t accumulate > any *more* error.The more I think about it the more I think that the ruby implementation of BigDecimal is flawed. BigDecimal(''1'') / BigDecimal(''3'') should be stored as a rational (ie as two values, 1 and 3 to be divided). Otherwise it seems to me that it is not ''proper'' BigDecimal. I have been unable to find documentation that fully defines what the result of 1/3 should be. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2010-Dec-25 00:37 UTC
Re: Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970536:> The more I think about it the more I think that the ruby > implementation of BigDecimal is flawed. BigDecimal(''1'') / > BigDecimal(''3'') should be stored as a rational (ie as two values, 1 > and 3 to be divided). Otherwise it seems to me that it is not ''proper'' > BigDecimal. I have been unable to find documentation that fully > defines what the result of 1/3 should be.I think differently here (but I may be mistaken ...). BigDecimal, for me, as the name implies, guarantees an "exact" representation of all numbers that are of the form: [+-] (d(n)*10^n + d(n-1)*10^(n-1) + ... + d(0)*10^0 + d(-1)*10^(-1) + ... d(-m)*10^(-m)) with d(n), the digit n places to the left of unity and d(-m), the digit m places to the right of the unit and the comma. The ^ (caret) represents the "to the power of" function (e.g. 10^3 == 1000). E.g. in the decimal number "3004.5006" d(3) = 3 d(2) = 0 d(1) = 0 d(0) = 4 d(-1) = 5 d(-2) = 0 d(-3) = 0 d(-4) = 6>> a = BigDecimal.new("3004.5006")=> #<BigDecimal:b72706c0,''0.30045006E4'',8(12)> These numbers form a (mathematical) field for the operators: +, -, * , but NOT with the division operator. The nice thing about BigDecimal is that it will automatically expand it''s precision if needed to make sure the representation remains correct when using the functions: +, -, *. There is always a finite (and exact) precision that is sufficient to represent the result of a [+-*] b Let''s try it:>> a = BigDecimal.new("1000000000000000000",12)=> #<BigDecimal:b725ae60,''0.1E19'',4(24)> # (precision automatically larger than the 12 I requested)>> b = BigDecimal.new("0.00000000000000003", 12)=> #<BigDecimal:b72320b4,''0.3E-16'',4(24)> # (precision automatically larger than the 12 I requested)>> sum = a+b=> #<BigDecimal:b722254c,''0.1000000000 0000000000 0000000000 000003E19'',40(56)> # nice, precision is enlarged to represent the _exact_ result :-)>> difference = a-b=> #<BigDecimal:b721ee9c,''0.9999999999 9999999999 9999999999 99997E18'',40(56)> # nice, precision is enlarged to represent the _exact_ result :-)>> product = a*b=> #<BigDecimal:b721c494,''0.3E2'',4(16)> # nice, precision is reduced because more is not required :-) But for the division ...>> division = a/b=> #<BigDecimal:b721aa7c,''0.3333333333 3333333333 3333333333 3333333333 3333333E35'',48(56)>>> division = a/bBigDecimal gives it a shot, takes a "large" precision ... but in a "Decimal" representation (Sum of d(i).10^i), there is no way to represent this exactly. So there is no limited value of precision that will allow the exact representation. Otherwise said, the function division ''/'' is not part of the field, it can produce results that are outside the set of decimals (even if the 2 operands are inside). The Decimal numbers are clearly a subset of the Rational numbers. It would be quite feasible to make a Rational class which is a field with the operators ''+'', ''-'', ''*'', ''/''. Of course, the Rational class exists and does this neatly:>> ra = Rational(1000000000000000000000000000,1)=> Rational(1000000000000000000000000000, 1)>> rb = Rational(2,1000000000000000000000000000)=> Rational(1, 500000000000000000000000000)>> ra.to_s=> "1000000000000000000000000000">> rb.to_s=> "1/500000000000000000000000000">> (ra+rb).to_s=> "500000000000000000000000000000000000000000000000000001/500000000000000000000000000">> (ra-rb).to_s=> "499999999999999999999999999999999999999999999999999999/500000000000000000000000000">> (ra*rb).to_s=> "2">> (ra/rb).to_s=> "500000000000000000000000000000000000000000000000000000">> (rb/ra).to_s=> "1/500000000000000000000000000000000000000000000000000000">> ra.inspect=> "Rational(1000000000000000000000000000, 1)">> rb.inspect=> "Rational(1, 500000000000000000000000000)" But then again ... sin, sqrt, etc. are not part of the field and will bring the result outside of the BigRational set into the set of "Real" numbers. My conclusion: * on the *, +, - operators, it is nice to see BigDecimal expand the precision of the results to stick to an "exact" representation and stay in the field. * if the BigDecimal class sticks to its definition of "Decimal" (and not Rational) then behavior of BigDecimal on the division operator can be nothing else then arbitrary. Possible solutions I see on top of my head: A do nothing (the result of division has a "large" precision, but is not "exact") B raise an exception if the representation becomes not exact C set an instance variable in the BigDecimal object that marks it is "not exact" (like the "tainted" flag) D let BigDecimal return a Rational if the result can not be exactly represented as a BigDecimal E use the Rational class if you want exact divisions ... They all have their advantages: * A OK. Understanding the behaviour is enough. I understand now that +.-,* work as expected and / causes the risk to loose exact representation. * B (could be Class or per object flag) ==> in bookkeeping applications, exactness is required, so any calculation that destroys the exactness must be flagged. So if you calculate the "average" profit over your 7 divisions, you would get an exception, unless you did something special and understand the risks * C this is really unintrusive and allows one to check at the end if the exactness did not get lost along the road * E this exists, use it if you want an "exact" representation of 1/3. I am not in favor of D because it silently changes the class of the result and this violates the principle of least surprise. If you want Rational, use it from the start then. HTH, Peter -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Colin Law
2010-Dec-25 12:38 UTC
Re: Re: Re: Re: Re: Weird issue with converting floats to integer
On 25 December 2010 00:37, Peter Vandenabeele <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Possible solutions I see on top of my head: > A do nothing (the result of division has a "large" precision, > but is not "exact") > B raise an exception if the representation becomes not exact > C set an instance variable in the BigDecimal object that marks > it is "not exact" (like the "tainted" flag) > D let BigDecimal return a Rational if the result can not be > exactly represented as a BigDecimal > E use the Rational class if you want exact divisions > ... > > They all have their advantages: > * A OK. Understanding the behaviour is enough. I understand > now that +.-,* work as expected and / causes the risk > to loose exact representation. > > * B (could be Class or per object flag) > ==> in bookkeeping applications, exactness is required, > so any calculation that destroys the exactness must > be flagged. So if you calculate the "average" profit > over your 7 divisions, you would get an exception, > unless you did something special and understand the risks > > * C this is really unintrusive and allows one to check at the > end if the exactness did not get lost along the road > > * E this exists, use it if you want an "exact" representation > of 1/3. > > I am not in favor of D because it silently changes the class > of the result and this violates the principle of least surprise. > If you want Rational, use it from the start then.For D there is no reason why the class of the result needs to change to Rational. It could stay as BigDecimal but internally store the data as a Rational. Looking at Java BigDecimal it throws an exception if the result of a division cannot be held exactly. In summary however I think you are correct for Ruby. BigDecimal will retain full accuracy except for division, where it is up to the user to make sure he/she understands what he is doing and ensures that errors are understood. Colin> > HTH, > > Peter > > -- > Posted via http://www.ruby-forum.com/. > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Vandenabeele
2010-Dec-25 13:11 UTC
Re: Re: Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970616:> On 25 December 2010 00:37, Peter Vandenabeele <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote:...>> I am not in favor of D because it silently changes the class >> of the result and this violates the principle of least surprise. >> If you want Rational, use it from the start then. > > For D there is no reason why the class of the result needs to change > to Rational. It could stay as BigDecimal but internally store the > data as a Rational.Ah, I see. I had not thought it that way. Thanks, Peter -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-25 14:24 UTC
Re: Re: Re: Re: Re: Weird issue with converting floats to integer
Peter Vandenabeele wrote in post #970618:> Colin Law wrote in post #970616: >> On 25 December 2010 00:37, Peter Vandenabeele <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >> wrote: > ... >>> I am not in favor of D because it silently changes the class >>> of the result and this violates the principle of least surprise. >>> If you want Rational, use it from the start then. >> >> For D there is no reason why the class of the result needs to change >> to Rational. It could stay as BigDecimal but internally store the >> data as a Rational.In this case there would be no advantage to storing as a Rational. Sounds like you want an ExactNumber class that abstracts both. For the record, I think BigDecimal / BigDecimal = BigDecimal is the correct design.> > Ah, I see. I had not thought it that way. > > Thanks, > > PeterBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Colin Law
2010-Dec-25 17:33 UTC
Re: Re: Re: Re: Re: Re: Weird issue with converting floats to integer
On 25 December 2010 14:24, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Peter Vandenabeele wrote in post #970618: >> Colin Law wrote in post #970616: >>> On 25 December 2010 00:37, Peter Vandenabeele <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >>> wrote: >> ... >>>> I am not in favor of D because it silently changes the class >>>> of the result and this violates the principle of least surprise. >>>> If you want Rational, use it from the start then. >>> >>> For D there is no reason why the class of the result needs to change >>> to Rational. It could stay as BigDecimal but internally store the >>> data as a Rational. > > In this case there would be no advantage to storing as a Rational. > Sounds like you want an ExactNumber class that abstracts both. > > For the record, I think BigDecimal / BigDecimal = BigDecimal is the > correct design.In an earlier post I think it was suggested that an advantage of BigDecimal is that errors do not increase. With divide as it is, and choosing 16 digit accuracy, then BigDecimal is virtually identical to Float (assuming ruby Float is actually what would be known as double in C). Also errors will potentially increase every time a divide operation is performed. It seems that the default is actually 8 digit which is only single precision float accuracy. I see that http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic discusses exactly this problem and the use of Rationals to get around it. It seems to suggest that some languages do that. Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-25 20:15 UTC
Re: Re: Re: Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970648:> On 25 December 2010 14:24, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >>>> to Rational. It could stay as BigDecimal but internally store the >>>> data as a Rational. >> >> In this case there would be no advantage to storing as a Rational. >> Sounds like you want an ExactNumber class that abstracts both. >> >> For the record, I think BigDecimal / BigDecimal = BigDecimal is the >> correct design. > > In an earlier post I think it was suggested that an advantage of > BigDecimal is that errors do not increase.Basically.> With divide as it is, and > choosing 16 digit accuracy, then BigDecimal is virtually identical to > Float (assuming ruby Float is actually what would be known as double > in C).Not at all! You can''t store 397 significant figures in a Float. You can in a BigDecimal. Apparently you are wilfully ignoring this advantage, since it has been brought up several times already.> Also errors will potentially increase every time a divide > operation is performed. It seems that the default is actually 8 digit > which is only single precision float accuracy. >So don''t use the default! Sheesh.> I see that http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic > discusses exactly this problem and the use of Rationals to get around > it. It seems to suggest that some languages do that.And that would be easy to do in Ruby. I''m glad we have a choice, though.> > ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Colin Law
2010-Dec-25 20:49 UTC
Re: Re: Re: Re: Re: Re: Re: Weird issue with converting floats to integer
On 25 December 2010 20:15, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Colin Law wrote in post #970648: >> On 25 December 2010 14:24, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >> wrote: >>>>> to Rational. It could stay as BigDecimal but internally store the >>>>> data as a Rational. >>> >>> In this case there would be no advantage to storing as a Rational. >>> Sounds like you want an ExactNumber class that abstracts both. >>> >>> For the record, I think BigDecimal / BigDecimal = BigDecimal is the >>> correct design. >> >> In an earlier post I think it was suggested that an advantage of >> BigDecimal is that errors do not increase. > > Basically. > >> With divide as it is, and >> choosing 16 digit accuracy, then BigDecimal is virtually identical to >> Float (assuming ruby Float is actually what would be known as double >> in C). > > Not at all! You can''t store 397 significant figures in a Float. You > can in a BigDecimal. Apparently you are wilfully ignoring this > advantage, since it has been brought up several times already.I am not at all saying there is no advantage to BigDecimal, merely exploring the issues. I entirely agree that for + - * there can be significant advantages. I am pointing out here that as soon as you get into more complex calculations involving division, or irrational numbers such as pi, and trig functions, square roots and so on that BigDecimal is not a panacea and will not guarantee that there are no errors in the calculations.>> Also errors will potentially increase every time a divide >> operation is performed. It seems that the default is actually 8 digit >> which is only single precision float accuracy. >> > > So don''t use the default! Sheesh.Right, again I was pointing out that one cannot blindly assume that BigDecimal is a panacea, it is necessary to understand ones problem and use the features appropriately. I am not suggesting you would not do that, others may not realise the issues however. It does seem strange to me that the default should be such low precision. It means that doing complex arithmetic with BigDecimal using the default precision one may get much greater errors than with Float.>> I see that http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic >> discusses exactly this problem and the use of Rationals to get around >> it. It seems to suggest that some languages do that. > > And that would be easy to do in Ruby. I''m glad we have a choice, > though.You misunderstand me, I was talking about the possibility of BigDecimal automatically using Rationals internally when division is involved (if the division does not result in an exact result). So if one did BD(1) / BD(3) then the result would be exactly 1/3 and would be a BigDecimal. Internally it would be a Rational but the user would not need to know that. The Wikipedia article appeared to suggest that some languages automatically do that. Again I am not saying Ruby _should_ do that, merely exploring the issues again. I am not trying to have an argument here, I am learning a lot myself by researching the issues and value such discussions greatly. Did you have a chance to see whether for you the result of BD 1 / BD 3 where each was specified as 16 bit appeared to result in an 8 bit answer, and if so, why? Colin -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Marnen Laibow-Koser
2010-Dec-25 23:30 UTC
Re: Re: Re: Re: Re: Re: Re: Weird issue with converting floats to integer
Colin Law wrote in post #970667:> On 25 December 2010 20:15, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > wrote: >>>> correct design. >> >> Not at all! You can''t store 397 significant figures in a Float. You >> can in a BigDecimal. Apparently you are wilfully ignoring this >> advantage, since it has been brought up several times already. > > I am not at all saying there is no advantage to BigDecimal, merely > exploring the issues. I entirely agree that for + - * there can be > significant advantages. I am pointing out here that as soon as you > get into more complex calculations involving division, or irrational > numbers such as pi, and trig functions, square roots and so on that > BigDecimal is not a panacea and will not guarantee that there are no > errors in the calculations.OK, that I agree with. I thought you were going further.> >>> Also errors will potentially increase every time a divide >>> operation is performed. It seems that the default is actually 8 digit >>> which is only single precision float accuracy. >>> >> >> So don''t use the default! Sheesh. > > Right, again I was pointing out that one cannot blindly assume that > BigDecimal is a panacea, it is necessary to understand ones problem > and use the features appropriately. I am not suggesting you would not > do that, others may not realise the issues however. It does seem > strange to me that the default should be such low precision.And to me.> It means > that doing complex arithmetic with BigDecimal using the default > precision one may get much greater errors than with Float.Right.> >>> I see that http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic >>> discusses exactly this problem and the use of Rationals to get around >>> it. It seems to suggest that some languages do that. >> >> And that would be easy to do in Ruby. I''m glad we have a choice, >> though. > > You misunderstand me, I was talking about the possibility of > BigDecimal automatically using Rationals internally when division is > involved (if the division does not result in an exact result). So if > one did BD(1) / BD(3) then the result would be exactly 1/3 and would > be a BigDecimal. Internally it would be a Rational but the user would > not need to know that.Is that really a good idea? This is where I think you''re really arguing for a further abstraction as I already proposed.> The Wikipedia article appeared to suggest that > some languages automatically do that. Again I am not saying Ruby > _should_ do that, merely exploring the issues again.I''d want a symbolic math system like Mathematica to do that. I''m not sure if a general-purpose programming language should.> > I am not trying to have an argument here, I am learning a lot myself > by researching the issues and value such discussions greatly.Me too! This is fascinating.> > Did you have a chance to see whether for you the result of BD 1 / BD 3 > where each was specified as 16 bit appeared to result in an 8 bit > answer, and if so, why?Not yet. Even though I''m Jewish, Christmas has me really busy!> > ColinBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org Sent from my iPhone -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Fred Ballard
2010-Dec-27 00:23 UTC
Re: Re: Re: Re: Re: Re: Re: Re: Weird issue with converting floats to integer
Just a footnote to all of this. The difference between using a value for pi of 3.1415927 or 3.14159265, between 7 and 8 digits of precision, when calculating the circumference of the earth introduces a difference of less than a meter. All very reasonable, but I still found it surprising. I was taking a differential equations class from a very knowledgeable math professor who told us about it. He was also surprised to discover that such low precision in *pi* can lead to such precision in the physical world. Fred On Sat, Dec 25, 2010 at 5:30 PM, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org>wrote:> Colin Law wrote in post #970667: > > On 25 December 2010 20:15, Marnen Laibow-Koser <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > > wrote: > >>>> correct design. > >> > >> Not at all! You can''t store 397 significant figures in a Float. You > >> can in a BigDecimal. Apparently you are wilfully ignoring this > >> advantage, since it has been brought up several times already. > > > > I am not at all saying there is no advantage to BigDecimal, merely > > exploring the issues. I entirely agree that for + - * there can be > > significant advantages. I am pointing out here that as soon as you > > get into more complex calculations involving division, or irrational > > numbers such as pi, and trig functions, square roots and so on that > > BigDecimal is not a panacea and will not guarantee that there are no > > errors in the calculations. > > OK, that I agree with. I thought you were going further. > > > > >>> Also errors will potentially increase every time a divide > >>> operation is performed. It seems that the default is actually 8 digit > >>> which is only single precision float accuracy. > >>> > >> > >> So don''t use the default! Sheesh. > > > > Right, again I was pointing out that one cannot blindly assume that > > BigDecimal is a panacea, it is necessary to understand ones problem > > and use the features appropriately. I am not suggesting you would not > > do that, others may not realise the issues however. It does seem > > strange to me that the default should be such low precision. > > And to me. > > > It means > > that doing complex arithmetic with BigDecimal using the default > > precision one may get much greater errors than with Float. > > Right. > > > > >>> I see that http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic > >>> discusses exactly this problem and the use of Rationals to get around > >>> it. It seems to suggest that some languages do that. > >> > >> And that would be easy to do in Ruby. I''m glad we have a choice, > >> though. > > > > You misunderstand me, I was talking about the possibility of > > BigDecimal automatically using Rationals internally when division is > > involved (if the division does not result in an exact result). So if > > one did BD(1) / BD(3) then the result would be exactly 1/3 and would > > be a BigDecimal. Internally it would be a Rational but the user would > > not need to know that. > > Is that really a good idea? This is where I think you''re really arguing > for a further abstraction as I already proposed. > > > > The Wikipedia article appeared to suggest that > > some languages automatically do that. Again I am not saying Ruby > > _should_ do that, merely exploring the issues again. > > I''d want a symbolic math system like Mathematica to do that. I''m not > sure if a general-purpose programming language should. > > > > > I am not trying to have an argument here, I am learning a lot myself > > by researching the issues and value such discussions greatly. > > Me too! This is fascinating. > > > > > Did you have a chance to see whether for you the result of BD 1 / BD 3 > > where each was specified as 16 bit appeared to result in an 8 bit > > answer, and if so, why? > > Not yet. Even though I''m Jewish, Christmas has me really busy! > > > > > Colin > > Best, > -- > Marnen Laibow-Koser > http://www.marnen.org > marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org > > Sent from my iPhone > > -- > Posted via http://www.ruby-forum.com/. > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to > rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<rubyonrails-talk%2Bunsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> > . > For more options, visit this group at > http://groups.google.com/group/rubyonrails-talk?hl=en. > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.