Unable to match distance computed in geocoder - ruby-on-rails

As per geocoder official doc:
Distance between Eiffel Tower and Empire State Building
Geocoder::Calculations.distance_between([47.858205,2.294359], [40.748433,-73.985655])
=> 3619.77359999382 # in configured units (default miles)
def geodistance
render json: Geocoder::Calculations.distance_between([47.858205,2.294359], [40.748433,-73.985655])
end
In my case I am getting the value to be:
=> 3648.3340765758867
Unit configurations are unchanged, not sure what can go wrong!

irb(main):001:0> require 'geocoder'
true
irb(main):002:0> Geocoder::Calculations.distance_between([47.858205,2.294359], [40.748433,-73.985655])
3648.3340765758867
This one is my sample output.
IMO: Might be that you used different ruby or gem versions in each case or something...
It would be nice to know in which environments did both of this code samples execute.
Use the source, Luke!
EDIT:
Might be something in this part of code:
a = (Math.sin(dlat / 2))**2 + Math.cos(point1[0]) *
(Math.sin(dlon / 2))**2 * Math.cos(point2[0])
c = 2 * Math.atan2( Math.sqrt(a), Math.sqrt(1-a))
c * earth_radius(options[:units])

Read me doc distance value :=> 3619.77359999382 is outdated.

Related

Consistant parse float values on uneven data

I have a list of float numbers, representing currency, and I need to turn them into integers, for precision.
The task is to turn float numbers into integers, likes:
0.95 => 95
1 => 100
1,465.01 => 146501
The problem is:
I don't have access to change the input csv files
The numbers came in a variety of ways (1.00, 1.0, 1, .95, 0.95, etc)
How can, safely, I turn these numbers into integers?
Some examples of my problem:
('16.81'.to_f * 100).to_i => 1680
('16.81'.to_f * 100_00).to_i / 100 => 1681
('342.28'.to_f * 100).to_i => 34228
('342.28'.to_f * 100_00).to_i / 100 => 34227
__ EDIT __
By the way, I'm using ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin19]
Floating point numbers can't necessarily represent all decimal numbers. This is explained in Is floating point math broken?. As such, when dealing with floats, you are always a bit uncertain and usually need to use rounding to get a desired number.
From your examples, ('16.81'.to_f * 100) results in 1680.9999999999998. Getting the integer value from that cuts off the fractional part, resulting in 1680. By using round instead, you can get the desired integer (which also solves the issue of partial cents). When relying on this, please note the details of how Ruby rounds exactly, specifically the optional half argument).
Instead of relying on Floats however, a better idea is to use BigDecimal numbers instead which allow arbitrary precision floating point numbers.
require 'bigdecimal'
(BigDecimal('16.81') * 100).round
# => 1681
(BigDecimal('.95') * 100).round
# => 95
number = '1,465.01'
# remove any "additional" characters
normalized = number.gsub(/[^-+0-9.]/, '')
(BigDecimal(normalized) * 100).round
# => 146501
In the last example, I have shown how you might cleanup your "human-readable" numbers for consistent parsing. Depending on your source data, you might need to perform additional changes (e.g. if you might have values such as '1.465,01' as is common in e.g. some European countries).
Use Bigdecimal for float numbers and append .to_i to convert it in integer
require 'bigdecimal'
(BigDecimal('16.81') * 100).to_i # 1681
(BigDecimal('342.28') * 100).to_i # 34228
For more details you can refer https://corainchicago.github.io/blog/why-does-ruby-add-numbers-wrong/

How to solve Mathematical Expressions in Rails 4 like 6000*70%?

I am using Dentaku gem to solve little complex expressions like basic salary is 70% of Gross salary. As the formulas are user editable so I worked on dentaku.
When I write calculator = Dentaku::Calculator.new to initialize and then enter the command calculator.evaluate("60000*70%") then error comes like below:
Dentaku::ParseError: Dentaku::AST::Modulo requires numeric operands
from /Users/sulman/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0/gems/dentaku-2.0.8/lib/dentaku/ast/arithmetic.rb:11:in `initialize'
I have array is which formula is stored like: ["EarningItem-5","*","6","7","%"] where EarningItem-5 is an object and has value 60000
How can I resolve such expressions?
For this particular case you can use basic_salary = gross_salary * 0.7
Next you need to create the number field in your views which accepts 0..100 range. At last, set up the after_save callback and use this code:
model
after_create :percent_to_float
protected
def percent_to_float
self.percent = percent / 100.0
self.save
end
edit:
Of course, you can simply use this formula without any callbacks:
basic_salary = gross_salary / 100.0 * 70
where 70 is user defined value.
Dentaku does not appear to support "percent". Try this instead
calculator.evaluate('60000 * 0.7')

Generating Random Fixed Decimal in Rails

I'm trying to generate random data in my rails application.
But I am having a problem with decimal amount. I get an error
saying bad value for range.
while $start < $max
$donation = Donation.new(member: Member.all.sample, amount: [BigDecimal('5.00')...BigDecimal('200.00')].sample,
date_give: Random.date_between(:today...Date.civil(2010,9,11)).to_date,
donation_reason: ['tithes','offering','undisclosed','building-fund'].sample )
$donation.save
$start +=1
end
If you want a random decimal between two numbers, sample isn't the way to go. Instead, do something like this:
random_value = (200.0 - 5.0) * rand() + 5
Two other suggestions:
1. if you've implemented this, great, but it doesn't look standard Random.date_between(:today...Date.civil(2010,9,11)).to_date
2. $variable means a global variable in Ruby, so you probably don't want that.
UPDATE --- way to really get random date
require 'date'
def random_date_between(first, second)
number_of_days = (first - second).abs
[first, second].min + rand(number_of_days)
end
random_date_between(Date.today, Date.civil(2010,9,11))
=> #<Date: 2012-05-15 ((2456063j,0s,0n),+0s,2299161j)>
random_date_between(Date.today, Date.civil(2010,9,11))
=> #<Date: 2011-04-13 ((2455665j,0s,0n),+0s,2299161j)>

Are there any solutions for translating measurement units on Rails?

I'd like to implement measurement unit preferences in a Ruby on Rails app.
For instance, the user should be able to select between displaying distances in miles or in kilometers. And, obviously, not only displaying, but entering values, too.
I suppose all values should be stored in one global measurement system to simplify calculations.
Are there any drop-in solutions for this? Or should I maybe write my own?
The ruby gem "ruby-units" may help:
http://ruby-units.rubyforge.org/ruby-units/
require 'rubygems'
require 'ruby-units'
'8.4 mi'.to('km') # => 13.3576 km
'8 lb 8 oz'.to('kg') # => 3.85554 kg
a = '3 in'.to_unit
b = Unit('5 cm')
a + b # => 4.968 in
(a + b).to('cm') # => 16.62 cm
You can maybe have a look at this gem, which let's you perform some unit conversions.
Quantity on Github
I built Unitwise to solve most unit conversion and measurement math problems in Ruby.
Simple usage looks like this:
require 'unitwise/ext'
26.2.mile.convert_to('km')
# => #<Unitwise::Measurement 42.164897129794255 kilometer>
If you want store measurements in your Rails models, you could do something like this:
class Race < ActiveRecord::Base
# Convert value to kilometer and store the number
def distance=(value)
super(value.convert_to("kilometer").to_f)
end
# Convert the database value to kilometer measurement when retrieved
def distance
super.convert_to('kilometer')
end
end
# Then you could do
five_k = Race.new(distance: 5)
five_k.distance
# => #<Unitwise::Measurement 5 kilometer>
marathon = Race.new(distance: 26.2.mile)
marathon.distance.convert_to('foot')
# => #<Unitwise::Measurement 138336.27667255333 foot>
Quick search on GitHub turned up this: http://github.com/collectiveidea/measurement
Sounds like it does what you need (as far as converting between units), but I can't say I've used it myself.
Edit: Pierre's gem looks like it's more robust and active.

Ruby: Math functions for Time Values

How do I add/subtract/etc. time values in Ruby? For example, how would I add the following times?
00:00:59 + 00:01:43 + 00:20:15 = ?
Use ActiveSupport, which has a ton of built-in date extensions.
require 'active_support/core_ext'
t1 = "#{Date.today} 00:00:59".to_time
t2 = "#{Date.today} 00:01:43".to_time
t3 = "#{Date.today} 00:20:15".to_time
t1.since(t2.seconds_since_midnight+t3.seconds_since_midnight)
or, if you don't care about the date, only time:
t1.since(t2.seconds_since_midnight+t3.seconds_since_midnight).strftime("%H:%M:%S")
For a full list, check out http://guides.rubyonrails.org/active_support_core_extensions.html#extensions-to-date
Kind of ugly, but you could use DateTime.parse(each_interval) & calculate the number of seconds in each. Like this:
require 'date'
def calc_seconds(time_string)
date_time = DateTime.parse(time_string)
hour_part = date_time.hour * 60 * 60
minute_part = date_time.minute * 60
second_part = date_time.second
hour_part + minute_part + second_part
end
...which gives you your result in seconds, assuming valid inputs. At which point you can add them together.
You could reverse the process to get the interval in your original notation.
I really think there ought to be an easier method, but I don't know of one.
One way would be to convert everything to seconds and then performing the operations... Then you would need to convert it again to a time object with
Time.at(seconds_result).strftime('%H:%M:%S')
And you would get the time nicely formatted (as a string).
I am trying to find a gem that does this, and other operations.
You probably want to use a gem that does not concern itself with the actual day. You could perform acrobatics using DateTime and or Time, but you would constantly be battling how to handle days.
One gem that may be useful is tod (TimeOfDay), https://github.com/JackC/tod
With that you could directly do TimeOfDay.parse "00:01:43", add the values, and print the result using strftime("%H:%M:%S").

Resources