Skip to content

Commit

Permalink
0.1.9 refactor - experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
RobTillaart committed Apr 26, 2020
1 parent 6412eef commit 052a401
Show file tree
Hide file tree
Showing 11 changed files with 1,103 additions and 2 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 Rob Tillaart
Copyright (c) 2015-2020 Rob Tillaart

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,30 @@
# Fraction
Arduino library to implement a Fraction datatype

Arduino library to implement a Fraction datatype (experimental)

## Description

The fraction library implements fractional numbers a.k.a. Q,
(integers are Z and floats/doubles are R),
and the conversion to floats.

The code is working with a number of limitations among others:
- denominator is max 4 digits to keep code for multiply and divide simple
- Fractions are not exact (even floats are not exact)
- the range of numbers supported is limited.
- code is experimental still.

That said, the library is useful e.g. to display float numbers as a fraction.
From programming point of view the fractionize function, converting a double
into a fraction is a nice programming problem, fast with a minimal error.

In short, use fractions with care otherwise your sketch might get broken ;)

## Operations

See examples

## Use with care

The library is reasonably tested, and if problems arise please let me know.

66 changes: 66 additions & 0 deletions examples/FractionFindSum/FractionFindSum.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// FILE: FractionFindSum.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.1
// PURPOSE: demo
// DATE: 13-feb-2015
// URL: https://github.com/RobTillaart/Fraction
//

#include "fraction.h"

uint32_t start;
uint32_t stop;

void setup()
{
pinMode(13, OUTPUT);
Serial.begin(115200);
Serial.print("\n\nStart F: ");
Serial.println(FRACTIONLIBVERSION);
Serial.println();
randomSeed(analogRead(A0) * 256 + analogRead(A1));

start = micros();
stop = micros();
// Serial.println(stop - start);

for (int i = 1; i < 93; i++)
{
Fraction f(i, 93);
findSum(f);
}
}

void findSum(Fraction f)
{
Fraction z(0);

Serial.print(f);
Serial.print(" =\t ");
for (long i = 1; i < 10000; i++)
{
Fraction g(1, i);
if (g <= f)
{
f -= g;
z += g;
Serial.print(g);
Serial.print(" + ");
}
if (f == Fraction(0))
{
break;
}
}
Serial.print("\t => ");
Serial.println(z);
Serial.println();
}


void loop()
{
}

// -- END OF FILE --
108 changes: 108 additions & 0 deletions examples/FractionMediant/FractionMediant.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//
// FILE: FractionMediant.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: Find fraction by binary search with mediant.
// DATE: 2020-04-21
//

// this method is not that fast but it shows a nice application for
// the mediant.

#include "fraction.h"

uint32_t start, stop;

void setup()
{
Serial.begin(115200);
Serial.print(__FILE__);
Serial.println();
Serial.println();

float f = PI;
start = micros();
Fraction x = fractionize(f);
stop = micros();
Serial.println(stop - start);
Serial.println(x);
Serial.println(x.toDouble(), 10);
Serial.println();

f = EULER;
start = micros();
Fraction y = fractionize(f);
stop = micros();
Serial.println(stop - start);
Serial.println(y);
Serial.println(y.toDouble(), 10);
Serial.println();

Serial.println("done...\n");

}


void loop()
{
float f = random(1000000) * 0.000001;

// reference
start = micros();
Fraction y(f);
stop = micros();

Serial.println();
Serial.print(stop - start);
Serial.print("\t");
Serial.print(y);
Serial.print("\t");
Serial.print(f, 10);
Serial.print("\t");
Serial.print(y.toDouble(), 10);
Serial.print("\t");
Serial.println(f - y.toDouble(), 10);

// mediant method.
start = micros();
y = fractionize(f);
stop = micros();

Serial.print(stop - start);
Serial.print("\t");
Serial.print(y);
Serial.print("\t");
Serial.print(f, 10);
Serial.print("\t");
Serial.print(y.toDouble(), 10);
Serial.print("\t");
Serial.println(f - y.toDouble(), 10);
}


Fraction fractionize(float f)
{
float acc = 1e-6;
float d1 = 0;
float d2 = 0;
Fraction a(0, 1);
Fraction b(9999, 1);
Fraction q(f);

for (int i = 0; i < 500; i++)
{
Fraction c = Fraction::mediant(a, b); // NOTE middle(a,b) is slower and worse!
if ( c.toDouble() < f) a = c;
else b = c;

d1 = abs(f - a.toDouble());
d2 = abs(f - b.toDouble());
if (d1 < acc && d2 < acc) break;
}
if (d1 < d2) return a;
return b;
}



// -- END OF FILE --
Loading

0 comments on commit 052a401

Please sign in to comment.