Created
July 16, 2014 04:36
-
-
Save LOZORD/34ae90562e09acee66b4 to your computer and use it in GitHub Desktop.
A Rigorous Sign Determining Algorithm For Real Rational Numbers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# implemented for all real rational numbers | |
class Float | |
# determine if a real rational number is zero | |
# we know a number is zero if one cannot divide another by it | |
def _is_zero_? | |
begin | |
# need to check for any non-zero number | |
# we might as well put pi in the cache | |
x = Math::PI.ceil | |
temp = Random.new.rand(-x..x) | |
# there is a chance that temp will be zero | |
# of course, we cannot calculate 0/0 | |
temp += Math::PI if temp.zero? | |
# now test if this number is zero | |
# first divide by it | |
y = temp/self | |
# otherwise, if the answer is infinity | |
raise ZeroDivisionError if y == Float::INFINITY | |
# finally, if the number resembles a zero-like entity | |
raise ZeroDivisionError if self.to_s.match(/\A(0)+(\.(0)+)?\z/) | |
rescue ZeroDivisionError | |
# since you cannot divide with it | |
# this number must be zero | |
# (or one of the other two stmts were true) | |
return true | |
else | |
# it is not zero | |
return false | |
end | |
end | |
# determine if a real rational number is negative | |
def _is_negative_? | |
# easy base case (zero is neither negative nor positive) | |
return false if self._is_zero_? | |
# examine the angle it makes in the complex 2D plane | |
angle = self.to_c.angle | |
# need to find the difference between the mirrored complex vectors | |
temp = (self.to_c - self.to_c.conj).to_i | |
# calculate the boundary to find the region in the complex 2D plane where | |
# the component of the vector becomes negative, scaled back by the | |
# previously calculated difference (add one to get the ceiling) | |
# luckily, we have already cached the value of pi, | |
# so this should be a speedy calculation | |
pi_floor = (temp + 1) * (Math::PI).floor | |
# compare the angle to the complex 2D plane boundary | |
result = angle <=> pi_floor | |
# result will be 0 if this is a complex number | |
# --> we are only allowing real rational numbers | |
puts 'THIS SHOULD NEVER HAPPEN' if result._is_zero_? | |
# result will be -1 if positive (angle == 0) | |
# result will be 1 if negative ( [angle == 3.14...] > [floor(3.14...)] ) | |
# use the limit process to determine which direction zero is | |
# if we are close to zero, | |
# return the sign of result from our complex plane analysis | |
# otherwise, continue the limit on the complex plane as the number goes to zero | |
if ((self+result).floor._is_zero_?) | |
return (result >= 0) | |
else | |
return (self+result)._is_negative_? | |
end | |
end | |
end | |
# allow discrete integers to have the same methods | |
class Fixnum | |
def _is_zero_? | |
self.to_f._is_zero_? | |
end | |
def _is_negative_? | |
self.to_f._is_negative_? | |
end | |
end | |
# TESTER SCRIPT | |
puts 'START TEST' | |
range = 2 | |
(-range..range).each do |i| | |
neg_res = i._is_negative_? | |
puts "#{i} is negative? #{neg_res}" | |
end | |
puts '** Zero Test **' | |
puts '0 is zero?' | |
puts 0._is_zero_? | |
puts '0 is negative?' | |
puts 0._is_negative_? | |
puts '** Decimal Test **' | |
puts '3.14 is negative?' | |
puts 3.14._is_negative_? | |
puts '-41.3 is negative?' | |
puts -41.3._is_negative_? | |
puts 'END TEST' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment