how to compare complex decimal number with integer value - ruby-on-rails

I'm going to get all clinics that are near to my latitude and longitude. i did that with following method. the result of dist is a long value that i need to compare it with a integer value. i don't know why i get this error during the compare dist and distance which is a integer value.
this is my error:
NoMethodError (undefined method `<=' for (-2.693846638591123+0.0i):Complex):
and this is what everyhting that i did for this:
def get_clinic_list
ulat=params[:lat]
ulang=params[:lang]
distance=params[:distance]
#clinic=[]
Clinic.all.each do |clinic|
if clinic_distance(ulat,ulang,distance,clinic.id)
#doctor=DoctorProfile.find_by(user_id: clinic.user_id)
end
end
end
def clinic_distance(ulat, ulang,distance,clinic)
#clinic=Clinic.find(clinic)
diff_lat= ulat.to_f - #clinic.latitude.to_f
diff_lang= ulang.to_f - #clinic.longitude.to_f
#disc=Math.sqrt(((diff_lat*119.574)**2)+(diff_lang * Math.cos(diff_lat) * 111.320))
a=(diff_lat * 119.574) ** 2
b= diff_lang * Math.cos(diff_lat) * 111.320
c=a+b
logger.info "the c parameter is #{c}"
dist=Math.sqrt(c)
dist = dist ** 2
if dist <= distance
return true
else
return false
end
end

Complex numbers don't support <= or >= (although they do support ==)
Simplest solution is to get the absolute part of the number
if dist.abs <= distance

There was a mistake is pretty much every line of your clinic_distance method. I tried my best at correcting it, but I cannot test it without your data.
The problem isn't about Complex numbers. I don't know where this Complex number comes from, possibly from a negative c in your Math.sqrt(c).
EarthRadius = 6371 # km
OneDegree = EarthRadius * 2 * Math::PI / 360 # 1° latitude in km
def get_clinic_list
lat = params[:lat]
lon = params[:lang] # :lang???
max_distance = params[:distance] # :distance should probably be :max_distance
#clinic = [] # What do you do with this empty array?
Clinic.all.each do |clinic|
if distance_in_km(lat, lon, clinic.latitude, clinic.longitude) < max_distance
# Do you really want to keep overriding #doctor every time a clinic is found?
#doctor = DoctorProfile.find_by(user_id: clinic.user_id)
end
end
# You return every clinic, even ones far away...
end
def distance_in_km(lat1, lon1, lat2, lon2)
diff_lat = lat1.to_f - lat2.to_f
diff_lon = lon1.to_f - lon2.to_f
lat_km = diff_lat * OneDegree
lon_km = diff_lon * OneDegree * Math.cos(lat1.to_f * Math::PI / 180) # Math.cos expects a radian angle
Math.sqrt(lat_km**2 + lon_km**2)
end

Related

How to round Decimals to the First Significant Figure in Ruby

I am attempting to solve an edge case to a task related to a personal project.
It is to determine the unit price of a service and is made up of the total_amount and cost.
Examples include:
# 1
unit_price = 300 / 1000 # = 0.3
# 2
unit_price = 600 / 800 # = 0.75
# 3
unit_price = 500 / 1600 # = 0.3125
For 1 and 2, the unit_prices can stay as they are. For 3, rounding to 2 decimal places will be sufficient, e.g. (500 / 1600).round(2)
The issue arises when the float becomes long:
# 4
unit_price = 400 / 56000 # = 0.007142857142857143
What's apparent is that the float is rather long. Rounding to the first significant figure is the aim in such instances.
I've thought about using a regular expression to match the first non-zero decimal, or to find the length of the second part and apply some logic:
unit_price.match ~= /[^.0]/
unit_price.to_s.split('.').last.size
Any assistance would be most welcome
One should use BigDecimal for this kind of computation.
require 'bigdecimal'
bd = BigDecimal((400.0 / 56000).to_s)
#⇒ 0.7142857142857143e-2
bd.exponent
#⇒ -2
Example:
[10_000.0 / 1_000, 300.0 / 1_000, 600.0 / 800,
500.0 / 1_600, 400.0 / 56_000].
map { |bd| BigDecimal(bd.to_s) }.
map do |bd|
additional = bd.exponent >= 0 ? 0 : bd.exponent + 1
bd.round(2 - additional) # THIS
end.
map(&:to_f)
#⇒ [10.0, 0.3, 0.75, 0.31, 0.007]
You can detect the length of the zeros string with regex. It's a bit ugly, but it works:
def significant_round(number, places)
match = number.to_s.match(/\.(0+)/)
return number unless match
zeros = number.to_s.match(/\.(0+)/)[1].size
number.round(zeros+places)
end
pry(main)> significant_round(3.14, 1)
=> 3.14
pry(main)> significant_round(3.00014, 1)
=> 3.0001
def my_round(f)
int = f.to_i
f -= int
coeff, exp = ("%e" % f).split('e')
"#{coeff.to_f.round}e#{exp}".to_f + int
end
my_round(0.3125)
#=> 0.3
my_round(-0.3125)
#=> -0.3
my_round(0.0003625)
#=> 0.0004
my_round(-0.0003625)
#=> -0.0004
my_round(42.0031)
#=> 42.003
my_round(-42.0031)
#=> -42.003
The steps are as follows.
f = -42.0031
int = f.to_i
#=> -42
f -= int
#=> -0.0031000000000034333
s = "%e" % f
#=> "-3.100000e-03"
coeff, exp = s.split('e')
#=> ["-3.100000", "-03"]
c = coeff.to_f.round
#=> -3
d = "#{c}e#{exp}"
#=> "-3e-03"
e = d.to_f
#=> -0.003
e + int
#=> -42.003
To instead keep only the most significant digit after rounding, change the method to the following.
def my_round(f)
coeff, exp = ("%e" % f).split('e')
"#{coeff.to_f.round}e#{exp}".to_f
end
If f <= 0 this returns the same as the earlier method. Here is an example when f > 0:
my_round(-42.0031)
#=> -40.0

Rails rounding decimal to the nearest power of ten

I'm looking for a rails function that could return the number to the nearest power of ten(10,100,1000), and also need to support number between 0 and 1 (0.1, 0.01, 0.001):
round(9) = 10
round(19) = 10
round(79) = 100
round(812.12) = 1000
round(0.0321) = 0.01
round(0.0921) = 0.1
I've looking on : Round number down to nearest power of ten
the accepted answer using the length of the string, that can't applied to number between 0 and 1.
updated
Round up to nearest power of 10 this one seems great. But I still can't make it work in rails.
I'm not sure about any function which automatically rounds the number to the nearest power of ten. You can achieve it by running the following code:
def rounded_to_nearest_power_of_ten(value)
abs_value = value.abs
power_of_ten = Math.log10(abs_value)
upper_limit = power_of_ten.ceil
lower_limit = power_of_ten.floor
nearest_value = (10**upper_limit - abs_value).abs > (10**lower_limit - abs_value).abs ? 10**lower_limit : 10**upper_limit
value > 0 ? nearest_value : -1*nearest_value
end
Hope this helps.
Let's simplify your problem to the following form - let the input numbers be in the range [0.1, 1), how would rounding of such numbers look like then?
The answer would be simple - for numbers smaller than 0.5 we would return the number 0.1, for larger numbers it would be 1.0.
All we have to do is to make sure that our number will be in that range. We will "move" decimal separator and remember how many moves we made in second variable. This operation is called normalization.
def normalize(fraction)
exponent = 0
while fraction < (1.0/10.0)
fraction *= 10.0
exponent -= 1
end
while fraction >= 1.0
fraction /= 10.0
exponent += 1
end
[fraction, exponent]
end
Using above code you can represent any floating number as a pair of normalized fraction and exponent in base 10. To recreate original number we will move decimal point in opposite direction using formula
original = normalized * base^{exponent}
With data property normalized we can use it in our simple rounding method like that:
def round(number)
fraction, exponent = normalize(number)
if fraction < 0.5
0.1 * 10 ** exponent
else
1.0 * 10 ** exponent
end
end
if the number is >= 1.0, this should work.
10 ** (num.floor.to_s.size - ( num.floor.to_s[0].to_i > 4 ? 0 : 1))
Try this:
def round_tenth(a)
if a.to_f >= 1
return 10 ** (a.floor.to_s.size - ( a.floor.to_s[0].to_i > 4 ? 0 : 1))
end
#a = 0.0392
c = a.to_s[2..a.to_s.length]
b = 0
c.split('').each_with_index do |s, i|
if s.to_i != 0
b = i + 1
break
end
end
arr = Array.new(100, 0)
if c[b-1].to_i > 4
b -= 1
if b == 0
return 1
end
end
arr[b-1] = 1
return ("0." + arr.join()).to_f
end
class Numeric
def name
def helper x, y, z
num = self.abs
r = 1
while true
result = nil
if num.between?(x, y)
if num >= y/2.0
result = y.round(r+1)
else
result = x.round(r)
end
return self.negative? ? -result : result
end
x *= z; y *= z; r += 1
end
end
if self.abs < 1
helper 0.1, 1, 0.1
else
helper 1, 10, 10
end
end
end
Example
-0.049.name # => -0.01
12.name # => 10
and so on, you are welcome!

Love2D Lua error: attempt to call field 'isDown' (a nil value)

This is my code in Love2D:
function love.load()
ninja = love.graphics.newImage("Ninja.png")
x = 0
y = 0
speed = 256
end
function love.update(dt)
if love.keyboard.isDown("right") then
ninja = love.graphics.newImage("NinjaRight.png")
x = x + (speed * dt)
end
if love.keyboard.isDown("left") then
ninja = love.graphics.newImage("NinjaLeft.png")
x = x - (speed * dt)
end
if love.keyboard.isDown("down") then
y = y + (speed * dt)
end
if love.keyboard.isDown("up") then
y = y - (speed * dt)
end
if love.joystick.isDown(joystick, 1, 2, 3, 4) then
a = 5
end
end
function love.draw()
love.graphics.draw(ninja, x, y)
end
I want to make the game to recognize a controller when connected.
But when I run the game, I receive the error:
attempt to call field 'isDown'(a nil value)
Where is the problem?
Since LÖVE 0.9.0 Joystick related isDown() function is moved to another namespace/table/You name ir or more "object" like structure. [1]
So, in Your code You should use it something like this:
--Get table of all connected Joysticks:
local joysticks = love.joystick.getJoysticks()
--Pick first one:
local joystick = joysticks[1]
if joystick:isDown(1, 2, 3, 4) then
a = 5
end
Where joystick is Your Joystick object. [2]
Be aware, love.keyboard.isDown() usage haven't changed yet. But, I guess, it's about to too. Sooner or later.
[1] https://love2d.org/wiki/Joystick:isDown
[2] https://love2d.org/wiki/love.joystick.getJoysticks

self.method (params) Rails

I'm newbie and I would like to know if is it possible to define model methods with params. I mean. I have this method to calculate distances using spherical coordinates
#in my model
#Haversin formula to calculate distance between spherical coordinates
def self.distance(b)
rad_per_deg = Math::PI/180 # PI / 180
rkm = 6371 # Earth radius in kilometers
#rm = rkm * 1000 # Radius in meters
a=[]
a.push(self.lat)
a.spuh(self.long)
dlon_rad = (b[1]-a[1]) * rad_per_deg # Delta, converted to rad
dlat_rad = (b[0]-a[0]) * rad_per_deg
lat1_rad, lon1_rad = a.map! {|i| i * rad_per_deg }
lat2_rad, lon2_rad = b.map! {|i| i * rad_per_deg }
a = Math.sin(dlat_rad/2)**2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin(dlon_rad/2)**2
c = 2 * Math.asin(Math.sqrt(a))
distance=rkm * c
return distance
end
I want this to work like: obj.distance(b) where b is an array of latitude and longitude. But when I try this on irb I get:
NoMethodError: undefined method `distance' for #<Object:0x000000058854c8>
Probably I'm missing something.
class Meteo < ActiveRecord::Base
attr_accessible :date, :humidity, :lat, :long, :pressure, :temp, :town, :wind, :wind_direction
, :rain_quantity
#Haversin formula to calculate distance between spheric coordinates
def self.distance(b)
rad_per_deg = Math::PI/180 # PI / 180
rkm = 6371 # Earth radius in kilometers
#rm = rkm * 1000 # Radius in meters
a=[]
a.push(self.lat)
a.spuh(self.long)
dlon_rad = (b[1]-a[1]) * rad_per_deg # Delta, converted to rad
dlat_rad = (b[0]-a[0]) * rad_per_deg
lat1_rad, lon1_rad = a.map! {|i| i * rad_per_deg }
lat2_rad, lon2_rad = b.map! {|i| i * rad_per_deg }
a = Math.sin(dlat_rad/2)**2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin(dlon_rad/2)
**2
c = 2 * Math.asin(Math.sqrt(a))
distance=rkm * c
return distance
end
end
And I call this on irb like:
irb> m=Meteo.last
irb> b=[86.43971008189519, 23.477053751481986]
irb> m.distance(b)
Just remove self.
When you write def self.distance, you mean that the method will be called on the model class. You should use def distance if you want the method to be called on a model instance.
Compare:
class SomeModel
def self.distance
# ...
end
end
SomeModel.distance
With:
class SomeModel
def distance
# ...
end
end
obj = SomeModel.new
obj.distance
If I get you right, you are defining a class method (with def self.distance) but are calling it on an instance of that class (obj.distance(array)).
You should call the method on obj's class e.g. Meteo.distance(array).
Or simply define it as an instance method, by just leaving the self in method definition.
Hope, that helps

Number of Percentage in Ruby on Rails

I have a coupon model and i am trying to calculate how much you save from the original deal.
Coupons.rb
def original_deal
original_price
end
def our_deal
deal_price
end
def percentage_off
original_deal / our_deal * 100.ceil
end
Show.html
<%= number_to_percentage(#coupon.percentage_off, :precision => 2) %>
Coupon Info
original_price = £100.00
deal_price = £90.00
Results.
I get 111.11% as the answer. What am i missing?
Your discount percentage calculation is off. You need to find the difference between the original price and the new price. And divide it by the original price to get the discount percentage:
def percentage_off
(Float(original_deal - our_deal) / original_deal * 100).ceil
end
Your input example would now return (100 - 90) / 100 * 100 = 10
Here's an alternative, step-by-step calculation :)
original = 100.0
our = 90.0
our_relative = our / original # => 0.9
you_save = (1.0 - our_relative).round(2) # => 0.1
you_save_percents = (you_save * 100).round # => 10
The calculation is coming out correct. If you look at the values you provided and do the math you come up with the following equation:
100.00 / 90.00 = 1.11
then you do
1.11 * 100 = 111.11
If you want to calculate your savings percentage, try this:
(original_price - deal_price) / original_price * 100.ceil
Hopefully that helps you out.

Resources