diff --git a/Sd1/P/fraction/V2/.gitignore b/Sd1/P/fraction/V2/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..4e247eee2103b4d4a35eba38166587fee1391f0e --- /dev/null +++ b/Sd1/P/fraction/V2/.gitignore @@ -0,0 +1,4 @@ +/.settings +/target +/.classpath +/.project diff --git a/Sd1/P/fraction/V2/pom.xml b/Sd1/P/fraction/V2/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..ed320843959f3087d2f90de63b762337923aabd3 --- /dev/null +++ b/Sd1/P/fraction/V2/pom.xml @@ -0,0 +1,69 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>de.hdm-stuttgart.de.sd1</groupId> + <artifactId>fraction</artifactId> + <version>1.0</version> + <packaging>jar</packaging> + + <name>fraction</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <javadocDestdir>~/tmp</javadocDestdir> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.3.2</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.9.1</version> + <configuration> + <linksource>true</linksource> + <!-- Setting destDir interferes with taglet class --> + <additionalJOptions> + <additionalJOption>-d ${javadocDestdir}</additionalJOption> + </additionalJOptions> + + <taglets> + <taglet> + <tagletClass>de.hdm_stuttgart.de.sd1.taglet.HtmlExtensionTaglet</tagletClass> + </taglet> + </taglets> + <tagletpath>../../../../../../../ws/eclipse/HtmlExtensionTaglet/target/classes</tagletpath> + </configuration> + </plugin> + </plugins> + + <resources> + <resource> + <directory>src/main/java</directory> + <includes> + <include> **/*.properties</include> + </includes> + </resource> + </resources> + </build> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + </dependencies> +</project> diff --git a/Sd1/P/fraction/V2/src/main/java/de/hdm_stuttgart/mi/sd1/fraction/Driver.java b/Sd1/P/fraction/V2/src/main/java/de/hdm_stuttgart/mi/sd1/fraction/Driver.java new file mode 100644 index 0000000000000000000000000000000000000000..b7a075c44b3797de7f4ccb82658807c78b9cd90d --- /dev/null +++ b/Sd1/P/fraction/V2/src/main/java/de/hdm_stuttgart/mi/sd1/fraction/Driver.java @@ -0,0 +1,26 @@ +package de.hdm_stuttgart.mi.sd1.fraction; + +/** + * Playing with fraction objects, producing some output. + * + */ +public class Driver { + /** + * @param args unused + */ + public static void main(String[] args) { + + // Input + final Fraction + twoThird = new Fraction(2, 3), // Construct a fraction object (2/3) + threeSeven = new Fraction(3, 7); // Construct a fraction object (3/7) + + // Computed results + final Fraction + sum = twoThird.add(threeSeven), // (2/3) + (3/7) + product = twoThird.mult(threeSeven); // (2/3) * (3/7) + + System.out.println("(2/3) + (3/7) = (23/21) = " + sum.getValue()); + System.out.println("(2/3) * (3/7) = (2/7) = " + product.getValue()); + } +} diff --git a/Sd1/P/fraction/V2/src/main/java/de/hdm_stuttgart/mi/sd1/fraction/Fraction.java b/Sd1/P/fraction/V2/src/main/java/de/hdm_stuttgart/mi/sd1/fraction/Fraction.java new file mode 100644 index 0000000000000000000000000000000000000000..f502dc2e1dd253be47f0c10d2e7b88c38e117b2c --- /dev/null +++ b/Sd1/P/fraction/V2/src/main/java/de/hdm_stuttgart/mi/sd1/fraction/Fraction.java @@ -0,0 +1,165 @@ +package de.hdm_stuttgart.mi.sd1.fraction; + +/** + * Representing Fractions + * + */ +public class Fraction { + + long numerator,denominator; + + /** + * The greatest common divisor (GCD) of two given integer values. + * + * @param a The first integer value. + * @param b The second integer value + * @return The GCD of a and b + * + */ + public static long getGcd(long a, long b) { + + // Following http://www.math.rutgers.edu/~greenfie/gs2004/euclid.html + if (a < b) { // Swap the values of a and b + long tmp = a; + a = b; + b = tmp; + } + while (0 != b) { + long r = a % b; + a = b; + b = r; + } + return a; + } + + /** + * @param numerator The fraction's numerator. + * @param denominator The fraction's denominator. + */ + public Fraction(long numerator, long denominator) { + final long gcd = getGcd(numerator, denominator); + + setNumerator(numerator / gcd); + setDenominator(denominator / gcd); + } + /** + * @return The fraction's decimal value e.g. 1/3 = 0.3333... + */ + public double getValue(){ + return (double) numerator / denominator; + } + /** + * @return The fraction's numerator + */ + public long getNumerator() { + return numerator; + } + /** + * @param numerator Set the fraction's numerator. + */ + public void setNumerator(long numerator) { + this.numerator = numerator; + } + /** + * @return + * The fraction's denominator value + */ + public long getDenominator() { + return denominator; + } + /** + * + * @param denominator Set the fraction's denominator + */ + public void setDenominator(long denominator) { + this.denominator = denominator; + } + + /** + * Add a second fraction to the current instance. + * + * @param f A second fraction. + * + * @return The sum of the current instance and f according to: + * +{@html.extend <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"> + <mrow> + <mrow> + <mfrac> + <mi>a</mi> + <mi>b</mi> + </mfrac> + <mo>+</mo> + <mfrac> + <mi>x</mi> + <mi>y</mi> + </mfrac> + </mrow> + <mo>=</mo> + <mfrac> + <mrow> + <mrow> + <mi>a</mi> + <mi>y</mi> + </mrow> + <mo>+</mo> + <mrow> + <mi>b</mi> + <mi>x</mi> + </mrow> + </mrow> + <mrow> + <mi>b</mi> + <mi>y</mi> + </mrow> + </mfrac> + </mrow> +</math>} + */ + public Fraction add(Fraction f) { + + final long gcd = getGcd(denominator, f.denominator); + + return new Fraction( numerator * (f.denominator / gcd) + (denominator / gcd) * f.numerator, + (denominator / gcd) * f.denominator); + } + /** + * Multiply a second fraction by this instance + * @param f Building the product with this second fraction. + * @return The result of multiplying the current instance by f according to: + {@html.extend <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"> + <mrow> + <mrow> + <mrow> + <mfrac> + <mi>a</mi> + <mi>b</mi> + </mfrac> + <mfrac> + <mi>x</mi> + <mi>y</mi> + </mfrac> + </mrow> + <mo>=</mo> + <mfrac> + <mrow> + <mi>a</mi> + <mi>x</mi> + </mrow> + <mrow> + <mi>b</mi> + <mi>y</mi> + </mrow> + </mfrac> + </mrow> + </mrow> +</math>} + */ + public Fraction mult(Fraction f) { + final Fraction f1 = new Fraction(f.numerator, denominator), + f2 = new Fraction(numerator, f.denominator); + + return new Fraction(f1.numerator * f2.numerator, + f1.denominator * f2.denominator); + } +} diff --git a/Sd1/P/fraction/V2/src/test/java/de/hdm_stuttgart/mi/sd1/fraction/FractionTest.java b/Sd1/P/fraction/V2/src/test/java/de/hdm_stuttgart/mi/sd1/fraction/FractionTest.java new file mode 100644 index 0000000000000000000000000000000000000000..86e8bdda470e748e32c0cd6c8b149799d5a8fcac --- /dev/null +++ b/Sd1/P/fraction/V2/src/test/java/de/hdm_stuttgart/mi/sd1/fraction/FractionTest.java @@ -0,0 +1,47 @@ +package de.hdm_stuttgart.mi.sd1.fraction; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class FractionTest extends TestCase { + /** + * @return the suite of tests being tested + */ + public static Test suite() { + final TestSuite testsuite = new TestSuite("Testing Fractions (sum + product)"); + testsuite.addTestSuite(FractionTest.class); + return testsuite; } + + /** + * Sums and products of fractions + */ + public void testApp() { + + assertEquals(Fraction.getGcd(18, 12), 6); + assertEquals(Fraction.getGcd(56, 21), 7); + + // Input + final Fraction + twoThird = new Fraction(2, 3), // Construct a fraction object (2/3) + threeSeven = new Fraction(3, 7); // Construct a fraction object (3/7) + + // Computed results + final Fraction + sum = twoThird.add(threeSeven), // (2/3) + (3/7) + product = twoThird.mult(threeSeven); // (2/3) * (3/7) + + assertTrue(sum.getNumerator() == 23 && sum.getDenominator() == 21); + assertTrue(product.getNumerator() == 2 && product.getDenominator() == 7); + + final Fraction sum2 = new Fraction(5, 18).add(new Fraction(7, 12)); + assertTrue(sum2.getNumerator() == 31 && sum2.getDenominator() == 36); + + final Fraction product2 = new Fraction(5, 18).mult(new Fraction(12, 7)); + assertTrue(product2.getNumerator() == 10 && product2.getDenominator() == 21); + + } +} diff --git a/Sd1/swd1.xml b/Sd1/swd1.xml index 49b125bfd018276546ef5dd44d2543e27f631ad1..b4d476280238b86fc946a5cd051a3d7e456b8a87 100644 --- a/Sd1/swd1.xml +++ b/Sd1/swd1.xml @@ -3042,6 +3042,201 @@ Is 2016 a leap year? true</programlisting> <chapter xml:id="sd1Loop2"> <title>Lecture 9, Loops II</title> + <section xml:id="ed1FractionCancel"> + <title>Cancelling fractions</title> + + <qandaset defaultlabel="qanda" xml:id="sd1QandaFractionCancel"> + <title>Implementing cancellation</title> + + <qandadiv> + <qandaentry> + <question> + <para>We recall <xref linkend="sde1QandaFraction"/>. So far no + one keeps fractions to be in cancelled state. The call new + Fraction(4,8) will create an instance internally being + represented as <inlineequation> + <m:math display="inline"> + <m:mfrac> + <m:mi>4</m:mi> + + <m:mi>8</m:mi> + </m:mfrac> + </m:math> + </inlineequation> rather than <inlineequation> + <m:math display="inline"> + <m:mfrac> + <m:mi>1</m:mi> + + <m:mi>2</m:mi> + </m:mfrac> + </m:math> + </inlineequation>.</para> + + <para>Adding cancellation requires a loop implementing the <link + xlink:href="http://www.math.rutgers.edu/~greenfie/gs2004/euclid.html">Euclidean + algorithm</link> in order to find the greatest common divisor + (<acronym>GCD</acronym>) of two non-zero integer values.</para> + + <para>Read the above link and implement a private class method + getGcd(long, long) inside your <classname>Fraction</classname> + class:</para> + + <programlisting language="java"> public static long getGcd(long a, long b) { + // Following http://www.math.rutgers.edu/~greenfie/gs2004/euclid.html + return ??; + }</programlisting> + + <para>Now change the following implementation items:</para> + + <itemizedlist> + <listitem> + <para>The constructor should provide cancellation if + required, see introductory remark.</para> + </listitem> + + <listitem> + <para>The Methods <methodname>mult(...)</methodname> and + <methodname>add(...)</methodname> should cancel any + resulting Fraction instance. It might be worth to consider + handling possible overflow errors in a defensive + strategy.</para> + </listitem> + </itemizedlist> + + <para>Test your results.</para> + </question> + + <answer> + <para>Implementing <methodname>getGcd(</methodname>):</para> + + <programlisting language="java"> public static long getGcd(long a, long b) { + + // Following http://www.math.rutgers.edu/~greenfie/gs2004/euclid.html + if (a < b) { // Swap the values of a and b + long tmp = a; + a = b; + b = tmp; + } + while (0 != b) { + long r = a % b; + a = b; + b = r; + } + return a; + }</programlisting> + + <para>Modifying the constructor is straightforward. We simply + divide both numerator and denominator by the + <acronym>GCD</acronym> value:</para> + + <programlisting language="java"> public Fraction(long numerator, long denominator) { + final long gcd = getGcd(numerator, denominator); + + setNumerator(numerator / gcd); + setDenominator(denominator / gcd); + }</programlisting> + + <para>Its tempting to implement + <methodname>mult(...)</methodname> in a simple fashion:</para> + + <programlisting language="java"> public Fraction mult2(Fraction f) { + return new Fraction(numerator * f.numerator, + denominator * f.denominator); + }</programlisting> + + <para>This is however too shortsighted. Consider the example + <inlineequation> + <m:math display="inline"> + <m:mrow> + <m:mfrac> + <m:mi>4</m:mi> + + <m:mi>7</m:mi> + </m:mfrac> + + <m:mo>â¢</m:mo> + + <m:mfrac> + <m:mi>3</m:mi> + + <m:mi>2</m:mi> + </m:mfrac> + </m:mrow> + </m:math> + </inlineequation>. Our simple implementation proposal would + call <code>new Fraction(12, 14)</code> only to discover a GCD + value of 4. Having larger argument values this might cause an + unnecessary overflow. Moreover the GCD calculation will take + longer than needed.</para> + + <para>We may instead transform the term in question by + exchanging the numerators like <inlineequation> + <m:math display="inline"> + <m:mrow> + <m:mfrac> + <m:mi>3</m:mi> + + <m:mi>7</m:mi> + </m:mfrac> + + <m:mo>â¢</m:mo> + + <m:mfrac> + <m:mi>4</m:mi> + + <m:mi>2</m:mi> + </m:mfrac> + </m:mrow> + </m:math> + </inlineequation> to enable possible cancellations prior to + multiplying. Now the call <code>new Fraction(4,2)</code> will + construct the representation <inlineequation> + <m:math display="inline"> + <m:mfrac> + <m:mi>2</m:mi> + + <m:mi>1</m:mi> + </m:mfrac> + </m:math> + </inlineequation> and finishing the computation will yield the + correct result <inlineequation> + <m:math display="inline"> + <m:mfrac> + <m:mi>6</m:mi> + + <m:mi>7</m:mi> + </m:mfrac> + </m:math> + </inlineequation>. We should thus implement:</para> + + <programlisting language="java"> public Fraction mult(Fraction f) { + final Fraction f1 = new Fraction(f.numerator, denominator), + f2 = new Fraction(numerator, f.denominator); + + return new Fraction(f1.numerator * f2.numerator, + f1.denominator * f2.denominator); + }</programlisting> + + <para>Similar reflections yield to decomposing the denumerators + when implementing <methodname>add(...)</methodname>:</para> + + <programlisting language="java"> public Fraction add(Fraction f) { + + final long gcd = getGcd(denominator, f.denominator); + + return new Fraction( numerator * (f.denominator / gcd) + (denominator / gcd) * f.numerator, + (denominator / gcd) * f.denominator); + }</programlisting> + + <para>See complete <link + xlink:href="Ref/api/P/fraction/V2/src-html/de/hdm_stuttgart/mi/sd1/fraction/Fraction.html">implementation + here</link>.</para> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + </section> + <section xml:id="sd1SecExp"> <title>Building a private library of mathematical functions.</title>