Arithmetic/Rational/Objective-C: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{collection|Rational Arithmetic}}
{{collection|Rational Arithmetic}}

File <tt>frac.h</tt>
File <tt>frac.h</tt>
<syntaxhighlight lang="objective-c">

<lang objc>#import <Foundation/Foundation.h>
#import <Foundation/Foundation.h>


@interface RCRationalNumber : NSObject
@interface RCRationalNumber : NSObject
Line 13: Line 12:
BOOL withSign;
BOOL withSign;
}
}
+(RCRationalNumber *)valueWithNumerator:(int)num andDenominator: (int)den;
+(instancetype)valueWithNumerator:(int)num andDenominator: (int)den;
+(RCRationalNumber *)valueWithDouble: (double)fnum;
+(instancetype)valueWithDouble: (double)fnum;
+(RCRationalNumber *)valueWithInteger: (int)inum;
+(instancetype)valueWithInteger: (int)inum;
+(RCRationalNumber *)valueWithRational: (RCRationalNumber *)rnum;
+(instancetype)valueWithRational: (RCRationalNumber *)rnum;
-(instancetype)initWithNumerator: (int)num andDenominator: (int)den;
-(id)init;
-(id)initWithNumerator: (int)num andDenominator: (int)den;
-(instancetype)initWithDouble: (double)fnum precision: (int)prec;
-(instancetype)initWithInteger: (int)inum;
-(id)initWithDouble: (double)fnum precision: (int)prec;
-(instancetype)initWithRational: (RCRationalNumber *)rnum;
-(id)initWithInteger: (int)inum;
-(id)initWithRational: (RCRationalNumber *)rnum;
-(NSComparisonResult)compare: (RCRationalNumber *)rnum;
-(NSComparisonResult)compare: (RCRationalNumber *)rnum;
-(id)simplify: (BOOL)act;
-(id)simplify: (BOOL)act;
Line 49: Line 47:
-(double)number;
-(double)number;
-(int)integer;
-(int)integer;
@end</lang>
@end</syntaxhighlight>
;File <tt>frac.m</tt>


<syntaxhighlight lang="objective-c">
File <tt>frac.m</tt>
#import <Foundation/Foundation.h>

<lang objc>#import <Foundation/Foundation.h>
#import <math.h>
#import <math.h>
#import "frac.h"
#import "frac.h"
Line 67: Line 65:
@implementation RCRationalNumber
@implementation RCRationalNumber
// initializers
// initializers
-(id)init
-(instancetype)init
{
{
NSLog(@"initialized to unity");
NSLog(@"initialized to unity");
Line 73: Line 71:
}
}


-(id)initWithNumerator: (int)num andDenominator: (int)den
-(instancetype)initWithNumerator: (int)num andDenominator: (int)den
{
{
if ((self = [super init]) != nil) {
if ((self = [super init]) != nil) {
Line 89: Line 87:
}
}


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


-(id)initWithDouble: (double)fnum precision: (int)prec
-(instancetype)initWithDouble: (double)fnum precision: (int)prec
{
{
if ( prec > 9 ) prec = 9;
if ( prec > 9 ) prec = 9;
Line 102: Line 100:
}
}


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


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


Line 257: Line 255:


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


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


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


+(RCRationalNumber *)valueWithRational: (RCRationalNumber *)rnum
+(instancetype)valueWithRational: (RCRationalNumber *)rnum
{
{
return [[[RCRationalNumber alloc] initWithRational: rnum] autorelease];
return [[self alloc] initWithRational: rnum];
}
}
@end</lang>
@end</syntaxhighlight>


Testing it.
;Testing
<syntaxhighlight lang="objective-c">

<lang objc>#import <Foundation/Foundation.h>
#import <Foundation/Foundation.h>
#import "frac.h"
#import "frac.h"
#import <math.h>
#import <math.h>
Line 286: Line 284:
int main()
int main()
{
{
@autoreleasepool {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];


int i;
int i;
for(i=2; i < 0x80000; i++) {
for(i=2; i < 0x80000; i++) {
int candidate = i;
int candidate = i;
RCRationalNumber *sum = [RCRationalNumber valueWithNumerator: 1
RCRationalNumber *sum = [RCRationalNumber valueWithNumerator: 1
andDenominator: candidate];
andDenominator: candidate];
int factor;
int factor;
for(factor=2; factor < sqrt((double)candidate); factor++) {
for(factor=2; factor < sqrt((double)candidate); factor++) {
if ( (candidate % factor) == 0 ) {
if ( (candidate % factor) == 0 ) {
sum = [[sum add: [RCRationalNumber valueWithNumerator: 1
sum = [[sum add: [RCRationalNumber valueWithNumerator: 1
andDenominator: factor]]
andDenominator: factor]]
add: [RCRationalNumber valueWithNumerator: 1
add: [RCRationalNumber valueWithNumerator: 1
andDenominator: (candidate/factor)]];
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!" : "");
}
}
}
}

if ( [sum denominator] == 1 ) {
printf("Sum of recipr. factors of %d = %d exactly %s\n",
candidate, [sum integer], ([sum integer]==1) ? "perfect!" : "");
}
}
}

[pool release];
return 0;
return 0;
}</lang>
}</syntaxhighlight>

Latest revision as of 08:20, 21 July 2023

Arithmetic/Rational/Objective-C is part of Rational Arithmetic. You may find other members of Rational Arithmetic at Category:Rational Arithmetic.

File frac.h

#import <Foundation/Foundation.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 <Foundation/Foundation.h>
#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 <Foundation/Foundation.h>
#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;
}