patternMinor
Immutable Fraction class
Viewed 0 times
immutableclassfraction
Problem
Inspired by this question: Fraction class implemented in Objective-C, I have written what I feel is an improved version of the Fraction class in Objective-C.
As per the tips in this answer, the class is immutable (and a mutable subclass might eventually happen). Besides improving on the existing functionality and changing to an immutable object, I also added the necessary methods for comparing fractions to other objects, other fractions, and importantly adding the
`
As per the tips in this answer, the class is immutable (and a mutable subclass might eventually happen). Besides improving on the existing functionality and changing to an immutable object, I also added the necessary methods for comparing fractions to other objects, other fractions, and importantly adding the
compare: method so that the fractions can be sorted!Fraction.h#import
@interface Fraction : NSObject
/*
An immutable class for representing and doing math
with rational numbers represented as fractions
with a numerator and denominator part.
*/
@property (readonly) NSInteger numerator;
@property (readonly) NSInteger denominator;
- (instancetype)initWithNumerator:(NSInteger)numerator
denominator:(NSInteger)denominator;
+ (instancetype)notANumber;
+ (instancetype)zero;
+ (instancetype)one;
+ (instancetype)fractionWithInteger:(NSInteger)integer;
+ (instancetype)fractionWithReciprocalOf:(NSInteger)integer;
+ (instancetype)fractionWithNumerator:(NSInteger)numerator
denominator:(NSInteger)denominator;
+ (instancetype)fractionWithFraction:(Fraction *)fraction;
// TODO: init with floating points.
- (instancetype)fractionByAddingFraction:(Fraction *)fraction;
- (instancetype)fractionBySubtractingFraction:(Fraction *)fraction;
- (instancetype)fractionByMultiplyingByFraction:(Fraction *)fraction;
- (instancetype)fractionByDividingByFraction:(Fraction *)fraction;
- (instancetype)reduced;
- (instancetype)reciprocal;
- (double)doubleValue;
- (float)floatValue;
- (int)intValue;
- (long)longValue;
- (NSInteger)integerValue;
- (BOOL)isEqualToFraction:(Fraction *)fraction;
- (NSComparisonResult)compare:(Fraction *)fraction;
@end
@interface NSNumber(Fraction)
+ (instancetype)numberWithFraction:(Fraction *)fraction;
@end`
Solution
One big issue I have with your code is that all of of your comparisons are based off of the fraction's double value. This can lead to many bugs down the line that result in questions like this.
To fix this: you can do one of two things: define or pass an epsilon (such as .00001) to be used for comparison.
Or even better, use the denominator and numerator to compare fractions.
To do so, I would utilize memoization (to make this performant for repeated calls on the same fraction), and to to store the fraction in reduced form. Then you do a simple comparison on the reduced form like so:
Compare \$xb\$ to \$ay\$:
To fix this: you can do one of two things: define or pass an epsilon (such as .00001) to be used for comparison.
Or even better, use the denominator and numerator to compare fractions.
To do so, I would utilize memoization (to make this performant for repeated calls on the same fraction), and to to store the fraction in reduced form. Then you do a simple comparison on the reduced form like so:
- Fraction 1: \$\dfrac{x}{y}\$
- Fraction 2: \$\dfrac{a}{b}\$
Compare \$xb\$ to \$ay\$:
- if \$xb > ay\$, Fraction 1 is bigger.
- if \$x*b
- if \$xb = ay\$, Fraction 1 is equal to Fraction 2.
Context
StackExchange Code Review Q#56936, answer score: 4
Revisions (0)
No revisions yet.