⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

{{collection|Rational Arithmetic}} ;File frac.h



@interface RCRationalNumber : NSObject
{
 @private
  int numerator;
  int denominator;
  BOOL autoSimplify;
  BOOL withSign;
}
+(instancetype)valueWithNumerator:(int)num andDenominator: (int)den;
+(instancetype)valueWithDouble: (double)fnum;
+(instancetype)valueWithInteger: (int)inum;
+(instancetype)valueWithRational: (RCRationalNumber *)rnum;
-(instancetype)initWithNumerator: (int)num andDenominator: (int)den;
-(instancetype)initWithDouble: (double)fnum precision: (int)prec;
-(instancetype)initWithInteger: (int)inum;
-(instancetype)initWithRational: (RCRationalNumber *)rnum;
-(NSComparisonResult)compare: (RCRationalNumber *)rnum;
-(id)simplify: (BOOL)act;
-(void)setAutoSimplify: (BOOL)v;
-(void)setWithSign: (BOOL)v;
-(BOOL)autoSimplify;
-(BOOL)withSign;
-(NSString *)description;
// ops
-(id)multiply: (RCRationalNumber *)rnum;
-(id)divide: (RCRationalNumber *)rnum;
-(id)add: (RCRationalNumber *)rnum;
-(id)sub: (RCRationalNumber *)rnum;
-(id)abs;
-(id)neg;
-(id)mod: (RCRationalNumber *)rnum;
-(int)sign;
-(BOOL)isNegative;
-(id)reciprocal;
// getter
-(int)numerator;
-(int)denominator;
//setter
-(void)setNumerator: (int)num;
-(void)setDenominator: (int)num;
// defraction
-(double)number;
-(int)integer;
@end

;File frac.m


#import <math.h>
#import "frac.h"

// gcd: [[Greatest common divisor#Recursive_Euclid_algorithm]]
// if built in as "private" function, add static.

static int lcm(int a, int b)
{
  return a / gcd(a,b) * b;
}

@implementation RCRationalNumber
// initializers
-(instancetype)init
{
  NSLog(@"initialized to unity");
  return [self initWithInteger: 1];
}

-(instancetype)initWithNumerator: (int)num andDenominator: (int)den
{
  if ((self = [super init]) != nil) {
    if (den == 0) {
      NSLog(@"denominator is zero");
      return nil;
    }
    [self setNumerator: num];
    [self setDenominator: den];
    [self setWithSign: YES];
    [self setAutoSimplify: YES];
    [self simplify: YES];
  }
  return self;
}

-(instancetype)initWithInteger:(int)inum
{
  return [self initWithNumerator: inum andDenominator: 1];
}

-(instancetype)initWithDouble: (double)fnum precision: (int)prec
{
  if ( prec > 9 ) prec = 9;
  double p = pow(10.0, (double)prec);
  int nd = (int)(fnum * p);
  return [self initWithNumerator: nd andDenominator: (int)p ];
}

-(instancetype)initWithRational: (RCRationalNumber *)rnum
{
  return [self initWithNumerator: [rnum numerator] andDenominator: [rnum denominator]];
}

// comparing
-(NSComparisonResult)compare: (RCRationalNumber *)rnum
{
  if ( [self number] > [rnum number] ) return NSOrderedDescending;
  if ( [self number] < [rnum number] ) return NSOrderedAscending;
  return NSOrderedSame;
}

// string rapresentation of the Q
-(NSString *)description
{
  [self simplify: [self autoSimplify]];
  return [NSString stringWithFormat: @"%@%d/%d", [self isNegative] ? @"-" : 
		     ( [self withSign] ? @"+" : @"" ),
		   abs([self numerator]), [self denominator]];
}

// setter options
-(void)setAutoSimplify: (BOOL)v
{
  autoSimplify = v;
  [self simplify: v];
}
-(void)setWithSign: (BOOL)v
{
  withSign = v;
}

// getter for options
-(BOOL)autoSimplify
{
  return autoSimplify;
}

-(BOOL)withSign
{
  return withSign;
}

// "simplify" the fraction ...
-(id)simplify: (BOOL)act
{
  if ( act ) {
    int common = gcd([self numerator], [self denominator]);
    [self setNumerator: [self numerator]/common];
    [self setDenominator: [self denominator]/common];
  }
  return self;
}

// diadic operators
-(id)multiply: (RCRationalNumber *)rnum
{
  int newnum = [self numerator] * [rnum numerator];
  int newden = [self denominator] * [rnum denominator];
  return [RCRationalNumber valueWithNumerator: newnum
			   andDenominator: newden];
}

-(id)divide: (RCRationalNumber *)rnum
{
  return [self multiply: [rnum reciprocal]];
}
 
-(id)add: (RCRationalNumber *)rnum
{
  int common = lcm([self denominator], [rnum denominator]);
  int resnum = common / [self denominator] * [self numerator] +
    common / [rnum denominator] * [rnum numerator];
  return [RCRationalNumber valueWithNumerator: resnum andDenominator: common];
}

-(id)sub: (RCRationalNumber *)rnum
{
  return [self add: [rnum neg]];
}

-(id)mod: (RCRationalNumber *)rnum
{
  return [[self divide: rnum] 
	   sub: [RCRationalNumber valueWithInteger: [[self divide: rnum] integer]]];
}

// unary operators
-(id)neg
{
  return [RCRationalNumber valueWithNumerator: -1*[self numerator]
			   andDenominator: [self denominator]];
}

-(id)abs
{
  return [RCRationalNumber valueWithNumerator: abs([self numerator])
			   andDenominator: [self denominator]];
}

-(id)reciprocal
{
  return [RCRationalNumber valueWithNumerator: [self denominator]
			   andDenominator: [self numerator]];
}

// get the sign
-(int)sign
{
  return ([self numerator] < 0) ? -1 : 1;
}

// or just test if negative
-(BOOL)isNegative
{
  return [self numerator] < 0;
}

// Q as real floating point
-(double)number
{
  return (double)[self numerator] / (double)[self denominator];
}

// Q as (truncated) integer
-(int)integer
{
  return [self numerator] / [self denominator];
}

// set num and den indipendently, fixing sign accordingly
-(void)setNumerator: (int)num
{
  numerator = num;
}

-(void)setDenominator: (int)num
{
  if ( num < 0 ) numerator = -numerator;
  denominator = abs(num);
}

// getter
-(int)numerator
{
  return numerator;
}

-(int)denominator
{
  return denominator;
}

// class method
+(instancetype)valueWithNumerator:(int)num andDenominator: (int)den
{
  return [[self alloc] initWithNumerator: num andDenominator: den];
}

+(instancetype)valueWithDouble: (double)fnum
{
  return [[self alloc] initWithDouble: fnum];
}

+(instancetype)valueWithInteger: (int)inum
{
  return [[self alloc] initWithInteger: inum];
}

+(instancetype)valueWithRational: (RCRationalNumber *)rnum
{
  return [[self alloc] initWithRational: rnum];
}
@end

;Testing


#import "frac.h"
#import <math.h>

int main()
{
  @autoreleasepool {

    int i;
    for(i=2; i < 0x80000; i++) {
      int candidate = i;
      RCRationalNumber *sum = [RCRationalNumber valueWithNumerator: 1
 			                            andDenominator: candidate];
      int factor;
      for(factor=2; factor < sqrt((double)candidate); factor++) {
        if ( (candidate % factor) == 0 ) {
 	  sum = [[sum add: [RCRationalNumber valueWithNumerator: 1
					         andDenominator: factor]]
		  add: [RCRationalNumber valueWithNumerator: 1
					     andDenominator: (candidate/factor)]];
        }
      }
      if ( [sum denominator] == 1 ) {
        printf("Sum of recipr. factors of %d = %d exactly %s\n",
	       candidate, [sum integer], ([sum integer]==1) ? "perfect!" : "");
      }
    }

  }
  return 0;
}