Created
October 4, 2014 17:55
-
-
Save douglashill/263637690cee8ed8a005 to your computer and use it in GitHub Desktop.
Continued fractions: convert real numbers to approximate fractions, such as 0.33 to 1/3 and π to 22/7.
This file contains hidden or 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
| @import Foundation; | |
| #define ENABLE_LOGGING 1 | |
| #if ENABLE_LOGGING | |
| #define DHLog(__FORMAT__, ...) NSLog((__FORMAT__), ##__VA_ARGS__) | |
| #else | |
| #define DHLog(...) do { } while (0) | |
| #endif | |
| typedef struct { | |
| int numerator; | |
| int denominator; | |
| } DHFraction; | |
| DHFraction DHFractionMake(int numerator, int denominator) | |
| { | |
| DHFraction fraction; | |
| fraction.numerator = numerator; | |
| fraction.denominator = denominator; | |
| return fraction; | |
| } | |
| DHFraction DHFractionAdd(int integer, DHFraction fraction) | |
| { | |
| DHFraction newFraction; | |
| newFraction.numerator = fraction.numerator + integer * fraction.denominator; | |
| newFraction.denominator = fraction.denominator; | |
| return newFraction; | |
| } | |
| NSString *DHStringFromFraction(DHFraction fraction) | |
| { | |
| return [NSString stringWithFormat:@"%d/%d", fraction.numerator, fraction.denominator]; | |
| } | |
| DHFraction continuedFraction(float number, float tolerance, int iterationLimit) | |
| { | |
| int integralComponent = floorf(number); | |
| float fractionalComponent = number - integralComponent; | |
| #if ENABLE_LOGGING | |
| DHLog(@"%d + %f", integralComponent, fractionalComponent); | |
| #endif | |
| if (ABS(1 - fractionalComponent) < tolerance) { | |
| DHLog(@"%f ~ 1", fractionalComponent); | |
| ++integralComponent; | |
| fractionalComponent = 0; | |
| DHLog(@"%d + %f *", integralComponent, fractionalComponent); | |
| } | |
| if (fractionalComponent < tolerance || iterationLimit <= 1) { | |
| if (fractionalComponent < tolerance) { | |
| DHLog(@"%f ~ 0", fractionalComponent); | |
| } | |
| else { | |
| DHLog(@"Reached iteration limit"); | |
| } | |
| return DHFractionMake(integralComponent, 1); | |
| } | |
| float reciprocal = 1 / fractionalComponent; | |
| DHFraction nextFraction = continuedFraction(reciprocal, tolerance, iterationLimit - 1); | |
| return DHFractionAdd(integralComponent, DHFractionMake(nextFraction.denominator, nextFraction.numerator)); | |
| } | |
| int main(int argc, const char * argv[]) { | |
| @autoreleasepool { | |
| float target = 0.33; | |
| float tolerance = 0.1; | |
| DHFraction fraction = continuedFraction(target, tolerance, 10); | |
| NSLog(@"%f = %@ %+g", target, DHStringFromFraction(fraction), target - ((float)fraction.numerator / fraction.denominator)); | |
| } | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment