class Fractify::Fraction
Attributes
denominator[RW]
negative[RW]
numerator[RW]
whole_part[RW]
Public Class Methods
floating_point_part(number)
click to toggle source
# File lib/fractify/fraction.rb, line 255 def self.floating_point_part(number) raise IncorrectArgumentsError unless number.is_a? Numeric result = '0.' number_string = number.to_s past_decimal_separator = false number_string.each_char do |c| if past_decimal_separator result += c elsif c == '.' past_decimal_separator = true end end result.to_f end
greatest_common_divisor(first, second)
click to toggle source
# File lib/fractify/fraction.rb, line 279 def self.greatest_common_divisor(first, second) return first if second.zero? greatest_common_divisor(second, first % second) end
least_common_multiple(first, second)
click to toggle source
# File lib/fractify/fraction.rb, line 273 def self.least_common_multiple(first, second) raise IncorrectArgumentsError unless first.is_a?(Numeric) && second.is_a?(Numeric) (first * second) / greatest_common_divisor(first, second) end
letter?(char)
click to toggle source
# File lib/fractify/fraction.rb, line 289 def self.letter?(char) char =~ /[[:alpha:]]/ end
new(whole_part: 0, numerator: 0, denominator: 1, string: '', numeric: false)
click to toggle source
# File lib/fractify/fraction.rb, line 10 def initialize(whole_part: 0, numerator: 0, denominator: 1, string: '', numeric: false) unless string.strip.empty? to_zero! parse_fraction_string!(string) return end if numeric.is_a? Numeric convert_number!(numeric) return end raise DividingByZeroError if denominator.zero? && numerator != 0 self.whole_part = whole_part self.numerator = numerator self.denominator = denominator self.negative = false fix_negativity! simplify! to_improper! end
numeric?(char)
click to toggle source
# File lib/fractify/fraction.rb, line 285 def self.numeric?(char) char =~ /[[:digit:]]/ end
valid?(string)
click to toggle source
# File lib/fractify/fraction.rb, line 249 def self.valid?(string) return false unless string.is_a? String validate_fraction_string(string) end
validate_float_string(string)
click to toggle source
# File lib/fractify/fraction.rb, line 386 def self.validate_float_string(string) open_bracket, incorrect_syntax, at_end, digit_present, floating_point_present = false minus_is_free = true string.each_char do |c| if at_end || letter?(c) incorrect_syntax = true break end if open_bracket if c == '-' if !minus_is_free || digit_present incorrect_syntax = true break end minus_is_free = false elsif numeric?(c) digit_present = true elsif c == '.' if floating_point_present || !digit_present incorrect_syntax = true break end floating_point_present = true elsif c == ')' open_bracket = false at_end = true else incorrect_syntax = true break end elsif c == '(' open_bracket = true else incorrect_syntax = true break end end incorrect_syntax = true if open_bracket !incorrect_syntax end
validate_fraction_string(string)
click to toggle source
# File lib/fractify/fraction.rb, line 293 def self.validate_fraction_string(string) is_float = false string.each_char do |c| if c == '.' is_float = true break end end if is_float validate_float_string(string) else validate_string(string) end end
validate_string(string)
click to toggle source
# File lib/fractify/fraction.rb, line 309 def self.validate_string(string) stage = 0 open_bracket, incorrect_syntax, at_end, digit_present = false minus_is_free = true string.each_char do |c| if at_end || letter?(c) incorrect_syntax = true break end if open_bracket if stage.zero? if c == '-' && minus_is_free minus_is_free = false elsif numeric?(c) digit_present = true elsif c == ' ' && digit_present stage = 1 minus_is_free = true digit_present = false elsif c == '/' && digit_present stage = 2 minus_is_free = true digit_present = false elsif c == ')' && digit_present else incorrect_syntax = true break end elsif stage == 1 if c == '-' && minus_is_free minus_is_free = false elsif numeric?(c) digit_present = true elsif c == '/' && digit_present stage = 2 minus_is_free = true digit_present else incorrect_syntax = true break end elsif stage == 2 if c == '-' && minus_is_free minus_is_free = false elsif numeric?(c) digit_present = true elsif c == ')' && digit_present else incorrect_syntax = true break end end end if c == '(' if open_bracket incorrect_syntax = true break end open_bracket = true elsif c == ')' unless open_bracket incorrect_syntax = true break end open_bracket = false at_end = true end end incorrect_syntax = true if open_bracket !incorrect_syntax end
Public Instance Methods
*(other)
click to toggle source
# File lib/fractify/fraction.rb, line 194 def *(other) check_argument(other) fraction = dup object = if other.is_a? Numeric Fractify::Fraction.new(numeric: other) else other.dup end fraction.to_improper! object.to_improper! negative_counter = 0 negative_counter += 1 if fraction.negative? negative_counter += 1 if object.negative? fraction.negative = negative_counter.even? ? false : true fraction.numerator *= object.numerator fraction.denominator *= object.denominator fraction.simplify! fraction.whole_part = 1 if fraction.zero? fraction end
**(other)
click to toggle source
# File lib/fractify/fraction.rb, line 239 def **(other) check_argument(other) if other.is_a? Numeric power(other) else x = other.to_f power(x) end end
+(other)
click to toggle source
# File lib/fractify/fraction.rb, line 173 def +(other) check_argument(other) fraction = dup object = if other.is_a? Numeric Fractify::Fraction.new(numeric: other) else other.dup end fraction.to_common_denominator!(object) unless object.zero? fraction.minus_to_numerator! object.minus_to_numerator! fraction.numerator += object.numerator fraction.minus_to_negative_field! fraction.simplify! fraction end
-(other)
click to toggle source
# File lib/fractify/fraction.rb, line 152 def -(other) check_argument(other) fraction = dup object = if other.is_a? Numeric Fractify::Fraction.new(numeric: other) else other.dup end fraction.to_common_denominator!(object) unless object.zero? fraction.minus_to_numerator! object.minus_to_numerator! fraction.numerator -= object.numerator fraction.minus_to_negative_field! fraction.simplify! fraction end
/(other)
click to toggle source
# File lib/fractify/fraction.rb, line 222 def /(other) check_argument(other) raise DividingByZeroError if other.zero? fraction = dup object = if other.is_a? Numeric Fractify::Fraction.new(numeric: other) else other.dup end object.to_reciprocal! fraction *= object fraction end
integer?()
click to toggle source
# File lib/fractify/fraction.rb, line 43 def integer? return true if denominator == 1 && !zero? false end
negative?()
click to toggle source
# File lib/fractify/fraction.rb, line 33 def negative? negative end
one?()
click to toggle source
# File lib/fractify/fraction.rb, line 49 def one? return true if numerator == 1 && denominator == 1 && whole_part.zero? false end
puts()
click to toggle source
# File lib/fractify/fraction.rb, line 97 def puts puts to_s end
simplify!()
click to toggle source
# File lib/fractify/fraction.rb, line 55 def simplify! return true if integer? if zero? @denominator = 1 @whole_part = 0 @negative = false else greatest_common_divisor = self.class.greatest_common_divisor(numerator, denominator) @denominator /= greatest_common_divisor @numerator /= greatest_common_divisor end true end
to_common_denominator!(other)
click to toggle source
# File lib/fractify/fraction.rb, line 432 def to_common_denominator!(other) to_improper! other.to_improper! least_common_multiple = self.class.least_common_multiple(denominator, other.denominator) numerator_multiplication = least_common_multiple / denominator @numerator *= numerator_multiplication @denominator = least_common_multiple numerator_multiplication = least_common_multiple / other.denominator other.numerator *= numerator_multiplication other.denominator = least_common_multiple true end
to_f()
click to toggle source
# File lib/fractify/fraction.rb, line 110 def to_f return 0.0 if zero? fraction = dup fraction.to_improper! fraction.minus_to_numerator! fraction.numerator.to_f / fraction.denominator end
to_i()
click to toggle source
# File lib/fractify/fraction.rb, line 120 def to_i return 0 if zero? fraction = dup fraction.to_proper_fraction! result = fraction.whole_part result = -result if fraction.negative? result end
to_improper!()
click to toggle source
# File lib/fractify/fraction.rb, line 87 def to_improper! return true if whole_part.zero? @numerator -= 1 if numerator == 1 && denominator == 1 @numerator += whole_part * denominator @whole_part = 0 true end
to_proper_fraction!()
click to toggle source
# File lib/fractify/fraction.rb, line 72 def to_proper_fraction! return true if zero? if denominator == 1 && numerator != 1 @whole_part += numerator @numerator = 1 elsif numerator > denominator new_whole_part = numerator / denominator @whole_part += new_whole_part @numerator %= denominator end true end
to_reciprocal!()
click to toggle source
# File lib/fractify/fraction.rb, line 449 def to_reciprocal! to_improper! aux = denominator @denominator = numerator @numerator = aux true end
to_s(improper = false)
click to toggle source
# File lib/fractify/fraction.rb, line 131 def to_s(improper = false) fraction = dup fraction.to_proper_fraction! unless improper fraction_string = '(' fraction_string += '-' if negative? if fraction.zero? fraction_string += '0' elsif fraction.one? fraction_string += '1' else fraction_string += fraction.whole_part.to_s if fraction.whole_part != 0 if fraction.numerator != 1 || fraction.denominator != 1 fraction_string += ' ' if fraction.whole_part != 0 fraction_string += fraction.numerator.to_s + '/' + fraction.denominator.to_s end end fraction_string + ')' end
to_zero!()
click to toggle source
# File lib/fractify/fraction.rb, line 101 def to_zero! @whole_part = 0 @numerator = 0 @denominator = 1 @negative = false true end
zero?()
click to toggle source
# File lib/fractify/fraction.rb, line 37 def zero? return true if numerator.zero? false end
Protected Instance Methods
minus_to_negative_field!()
click to toggle source
# File lib/fractify/fraction.rb, line 469 def minus_to_negative_field! return true unless numerator.negative? @negative = true @numerator = numerator.abs true end
minus_to_numerator!()
click to toggle source
# File lib/fractify/fraction.rb, line 460 def minus_to_numerator! return true unless negative @negative = false @numerator = -numerator true end
Private Instance Methods
arguments_make_negative?()
click to toggle source
# File lib/fractify/fraction.rb, line 521 def arguments_make_negative? negative_attributes = 0 %w[whole_part numerator denominator].each do |a| negative_attributes += 1 if send(a).negative? end return true if negative_attributes.odd? false end
check_argument(other)
click to toggle source
# File lib/fractify/fraction.rb, line 480 def check_argument(other) return unless !other.is_a?(Numeric) && !other.is_a?(Fractify::Fraction) raise IncorrectArgumentsError end
convert_number!(number)
click to toggle source
# File lib/fractify/fraction.rb, line 693 def convert_number!(number) if number.zero? to_zero! return end if number.negative? number = number.abs @negative = true end @whole_part = number.to_i new_denominator = 1 floating_point_part = self.class.floating_point_part(number) while floating_point_part.positive? floating_point_part *= new_denominator floating_point_part = self.class.floating_point_part(floating_point_part) new_denominator *= 10 end @numerator = self.class.floating_point_part(number) * new_denominator @numerator = numerator.to_i @denominator = new_denominator @numerator = 1 if numerator.zero? simplify! to_improper! end
fix_negativity!()
click to toggle source
# File lib/fractify/fraction.rb, line 511 def fix_negativity! @negative = !negative if arguments_make_negative? @whole_part = whole_part.abs @numerator = numerator.abs @denominator = denominator.abs true end
parse_float_string!(string)
click to toggle source
# File lib/fractify/fraction.rb, line 642 def parse_float_string!(string) number_string = '' open_bracket, incorrect_syntax, at_end, digit_present, floating_point_present = false minus_is_free = true string.each_char do |c| if at_end || self.class.letter?(c) incorrect_syntax = true break end if open_bracket if c == '-' if !minus_is_free || digit_present incorrect_syntax = true break end minus_is_free = false number_string += c elsif self.class.numeric?(c) digit_present = true number_string += c elsif c == '.' if floating_point_present || !digit_present incorrect_syntax = true break end floating_point_present = true number_string += c elsif c == ')' open_bracket = false at_end = true else incorrect_syntax = true break end elsif c == '(' open_bracket = true else incorrect_syntax = true break end end raise IncorrectStringSyntax if open_bracket || incorrect_syntax convert_number!(number_string.to_f) end
parse_fraction_string!(string)
click to toggle source
# File lib/fractify/fraction.rb, line 531 def parse_fraction_string!(string) is_float = false string.each_char do |c| if c == '.' is_float = true break end end if is_float parse_float_string!(string) else parse_string!(string) end end
parse_string!(string)
click to toggle source
# File lib/fractify/fraction.rb, line 547 def parse_string!(string) stage = 0 number_string = '' open_bracket, incorrect_syntax, at_end, digit_present = false minus_is_free = true string.each_char do |c| if at_end || self.class.letter?(c) incorrect_syntax = true break end if open_bracket if stage.zero? if c == '-' && minus_is_free @negative = true minus_is_free = false elsif self.class.numeric?(c) number_string += c digit_present = true elsif c == ' ' && digit_present stage = 1 @whole_part = number_string.to_i number_string = '' minus_is_free = true digit_present = false elsif c == '/' && digit_present stage = 2 @numerator = number_string.to_i number_string = '' minus_is_free = true digit_present = false elsif c == ')' && digit_present @numerator = number_string.to_i @denominator = 1 else incorrect_syntax = true break end elsif stage == 1 if c == '-' && minus_is_free @negative = !negative minus_is_free = false elsif self.class.numeric?(c) number_string += c digit_present = true elsif c == '/' && digit_present stage = 2 @numerator = number_string.to_i number_string = '' minus_is_free = true digit_present else incorrect_syntax = true break end elsif stage == 2 if c == '-' && minus_is_free @negative = !negative minus_is_free = false elsif self.class.numeric?(c) number_string += c digit_present = true elsif c == ')' && digit_present @denominator = number_string.to_i else incorrect_syntax = true break end end end if c == '(' if open_bracket incorrect_syntax = true break end open_bracket = true elsif c == ')' unless open_bracket incorrect_syntax = true break end open_bracket = false at_end = true end end raise IncorrectStringSyntax if incorrect_syntax || open_bracket simplify! end
power(x)
click to toggle source
# File lib/fractify/fraction.rb, line 486 def power(x) fraction = dup fraction.negative = false if (x % 2).zero? if x.negative? fraction.to_reciprocal! x = x.abs else fraction.to_improper! end if x == x.to_i fraction.numerator **= x.to_i fraction.denominator **= x.to_i fraction.simplify! else float = fraction.to_f.abs float **= x float = -float if fraction.negative? fraction = Fractify::Fraction.new(numeric: float) end fraction end