Converting Between Degrees and Radians

Problem

The trigonometry functions in Ruby's Math library take input in radians (2π radians in a circle). Most real-world applications measure angles in degrees (360 degrees in a circle). You want an easy way to do trigonometry with degrees.

Solution

The simplest solution is to define a conversion method in Numeric that will convert a number of degrees into radians.

	class Numeric
	 def degrees
	 self * Math::PI / 180 
	 end
	end

You can then treat any numeric object as a number of degrees and convert it into the corresponding number of radians, by calling its degrees method. Trigonometry on the result will work as you'd expect:

	90.degrees # => 1.5707963267949
	Math::tan(45.degrees) # => 1.0
	Math::cos(90.degrees) # => 6.12303176911189e-17
	Math::sin(90.degrees) # => 1.0
	Math::sin(89.9.degrees) # => 0.999998476913288

	Math::sin(45.degrees) # => 0.707106781186547
	Math::cos(45.degrees) # => 0.707106781186548

 

Discussion

I named the conversion method degrees by analogy to the methods like hours defined by Rails. This makes the code easy to read, but if you look at the actual numbers, it's not obvious why 45.degrees should equal the floating-point number 0.785398163397448.

If this troubles you, you could name the method something like degrees_to_radians. Or you could use Lucas Carlson's units gem, which lets you define customized unit conversions, and tracks which unit is being used for a particular number.

	require 'rubygems' 
	require 'units/base'

	class Numeric
	 remove_method(:degrees) # Remove the implementation given in the Solution
	 add_unit_conversions(:angle => { :radians => 1, :degrees => Math::PI/180 })
	 add_unit_aliases(:angle => { :degrees => [:degree], :radians => [:radian] })
	end

	90.degrees # => 90.0
	90.degrees.unit # => :degrees
	90.degrees.to_radians # => 1.5707963267949
	90.degrees.to_radians.unit # => :radians

	1.degree.to_radians # => 0.0174532925199433
	1.radian.to_degrees # => 57.2957795130823

The units you define with the units gem do nothing but make your code more readable. The trigonometry methods don't understand the units you've defined, so you'll still have to give them numbers in radians.

	# Don't do this:
	Math::sin(90.degrees) # => 0.893996663600558

	# Do this:
	Math::sin(90.degrees.to_radians) # => 1.0

Of course, you could also change the trigonometry methods to be aware of units:

	class << Math
	 alias old_sin sin
	 def sin(x)
	 old_sin(x.unit == :degrees ? x.to_radians : x)
	 end
	end

	90.degrees # => 90.0 
	Math::sin(90.degrees) # => 1.0
	Math::sin(Math::PI/2.radians) # => 1.0 
	Math::sin(Math::PI/2) # => 1.0

That's probably overkill, though.

See Also

  • Recipe 8.9, "Converting and Coercing Objects to Different Types"
  • The Facets More library (available as the facets_more gem) also has a Units module


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net