]> source.dussan.org Git - poi.git/commitdiff
Patch and unit test from Tim Allen from bug #54686 - Improve how DataFormatter handle...
authorNick Burch <nick@apache.org>
Thu, 20 Jun 2013 13:37:26 +0000 (13:37 +0000)
committerNick Burch <nick@apache.org>
Thu, 20 Jun 2013 13:37:26 +0000 (13:37 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1494986 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/poi/ss/usermodel/DataFormatter.java
src/java/org/apache/poi/ss/usermodel/FractionFormat.java [new file with mode: 0644]
src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
src/testcases/org/apache/poi/ss/usermodel/TestFractionFormat.java [new file with mode: 0644]
test-data/spreadsheet/54686_fraction_formats.txt [new file with mode: 0644]
test-data/spreadsheet/54686_fraction_formats.xls [new file with mode: 0644]

index 930f8b42075ad0188928d9bab8b623618495f6ce..46740cc3816557c9a8e4878db295970a1c4b36ff 100644 (file)
@@ -28,7 +28,6 @@ import java.text.DecimalFormat;
 import java.text.DecimalFormatSymbols;
 import java.text.FieldPosition;
 import java.text.Format;
-import java.text.NumberFormat;
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -41,7 +40,6 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.poi.ss.formula.eval.NotImplementedException;
 
 /**
  * DataFormatter contains methods for formatting the value stored in an
@@ -100,12 +98,10 @@ import org.apache.poi.ss.formula.eval.NotImplementedException;
  *  <li>simulate Excel's handling of a format string of all # when the value is 0.
  *   Excel will output "", <code>DataFormatter</code> will output "0".
  * </ul>
- * @author James May (james dot may at fmr dot com)
- * @author Robert Kish
-  *
  */
 public class DataFormatter {
-
+    private static final String defaultFractionWholePartFormat = "#";
+    private static final String defaultFractionFractionPartFormat = "#/##";
     /** Pattern to find a number format: "0" or  "#" */
     private static final Pattern numPattern = Pattern.compile("[0#]+");
 
@@ -131,6 +127,17 @@ public class DataFormatter {
                        "(\\[MAGENTA\\])|(\\[RED\\])|(\\[WHITE\\])|(\\[YELLOW\\])|" +
                        "(\\[COLOR\\s*\\d\\])|(\\[COLOR\\s*[0-5]\\d\\])", Pattern.CASE_INSENSITIVE);
 
+    /**
+     * A regex to identify a fraction pattern.
+     * This requires that replaceAll("\\?", "#") has already been called 
+     */
+    private static final Pattern fractionPattern = Pattern.compile("(?:([#\\d]+)\\s+)?(#+)\\s*\\/\\s*([#\\d]+)");
+
+    /**
+     * A regex to strip junk out of fraction formats
+     */
+    private static final Pattern fractionStripper = Pattern.compile("(\"[^\"]*\")|([^ \\?#\\d\\/]+)");
+
     /**
       * Cells formatted with a date or time format and which contain invalid date or time values
      *  show 255 pound signs ("#").
@@ -372,23 +379,26 @@ public class DataFormatter {
                 DateUtil.isValidExcelDate(cellValue)) {
             return createDateFormat(formatStr, cellValue);
         }
-        
         // Excel supports fractions in format strings, which Java doesn't
-        if (formatStr.indexOf("#/#") >= 0 || formatStr.indexOf("?/?") >= 0) {
-            // Strip custom text in quotes and escaped characters for now as it can cause performance problems in fractions.
-               String strippedFormatStr = formatStr.replaceAll("\\\\ ", " ").replaceAll("\\\\.", "").replaceAll("\"[^\"]*\"", " ");
-
-               boolean ok = true;
-               for (String part: strippedFormatStr.split(";")) {
-                       int indexOfFraction = indexOfFraction(part);
-                       if (indexOfFraction == -1 || indexOfFraction != lastIndexOfFraction(part)) {
-                               ok = false;
-                               break;
-                       }
-               }
-            if (ok) {
-                return new FractionFormat(strippedFormatStr);
+        if (formatStr.indexOf("#/") >= 0 || formatStr.indexOf("?/") >= 0) {
+            String[] chunks = formatStr.split(";");
+            for (int i = 0; i < chunks.length; i++){
+                String chunk = chunks[i].replaceAll("\\?", "#");
+                Matcher matcher = fractionStripper.matcher(chunk);
+                chunk = matcher.replaceAll(" ");
+                chunk = chunk.replaceAll(" +", " ");
+                Matcher fractionMatcher = fractionPattern.matcher(chunk);
+                //take the first match
+                if (fractionMatcher.find()){
+                    String wholePart = (fractionMatcher.group(1) == null) ? "" : defaultFractionWholePartFormat;
+                    return new FractionFormat(wholePart, fractionMatcher.group(3));
+                }
             }
+            
+            // Strip custom text in quotes and escaped characters for now as it can cause performance problems in fractions.
+            //String strippedFormatStr = formatStr.replaceAll("\\\\ ", " ").replaceAll("\\\\.", "").replaceAll("\"[^\"]*\"", " ").replaceAll("\\?", "#");
+            //System.out.println("formatStr: "+strippedFormatStr);
+            return new FractionFormat(defaultFractionWholePartFormat, defaultFractionFractionPartFormat);
         }
         
         if (numPattern.matcher(formatStr).find()) {
@@ -402,17 +412,7 @@ public class DataFormatter {
         return null;
     }
     
-    private int indexOfFraction(String format) {
-       int i = format.indexOf("#/#");
-       int j = format.indexOf("?/?");
-       return i == -1 ? j : j == -1 ? i : Math.min(i,  j);
-    }
-
-    private int lastIndexOfFraction(String format) {
-       int i = format.lastIndexOf("#/#");
-       int j = format.lastIndexOf("?/?");
-       return i == -1 ? j : j == -1 ? i : Math.max(i,  j);
-    }
 
     private Format createDateFormat(String pFormatStr, double cellValue) {
         String formatStr = pFormatStr;
@@ -786,7 +786,7 @@ public class DataFormatter {
      * @return a string value of the cell
      */
     public String formatCellValue(Cell cell, FormulaEvaluator evaluator) {
-
+        
         if (cell == null) {
             return "";
         }
@@ -1018,97 +1018,9 @@ public class DataFormatter {
         }
     }
     
-    /**
-     * Format class that handles Excel style fractions, such as "# #/#" and "#/###"
-     */
-    @SuppressWarnings("serial")
-    private static final class FractionFormat extends Format {
-       private final String str;
-       public FractionFormat(String s) {
-          str = s;
-       }
-       
-       public String format(Number num) {
-          
-         double doubleValue = num.doubleValue();
-          
-          // Format may be p or p;n or p;n;z (okay we never get a z).
-         // Fall back to p when n or z is not specified.
-          String[] formatBits = str.split(";");
-          int f = doubleValue > 0.0 ? 0 : doubleValue < 0.0 ? 1 : 2; 
-          String str = (f < formatBits.length) ? formatBits[f] : formatBits[0];
-          
-          double wholePart = Math.floor(Math.abs(doubleValue));
-          double decPart = Math.abs(doubleValue) - wholePart;
-          if (wholePart + decPart == 0) {
-             return "0";
-          }
-          if (doubleValue < 0.0) {
-                 wholePart *= -1.0;
-          }
-
-          // Split the format string into decimal and fraction parts
-          String[] parts = str.replaceAll("  *", " ").split(" ");
-          String[] fractParts;
-          if (parts.length == 2) {
-             fractParts = parts[1].split("/");
-          } else {
-             fractParts = str.split("/");
-          }
-          
-          // Excel supports both #/# and ?/?, but Java only the former
-          for (int i=0; i<fractParts.length; i++) {
-             fractParts[i] = fractParts[i].replace('?', '#');
-          }
-
-          if (fractParts.length == 2) {
-                int fractPart1Length = Math.min(countHashes(fractParts[1]), 4); // Any more than 3 and we go around the loops for ever
-             double minVal = 1.0;
-             double currDenom = Math.pow(10 ,  fractPart1Length) - 1d;
-             double currNeum = 0;
-             for (int i = (int)(Math.pow(10,  fractPart1Length)- 1d); i > 0; i--) {
-                for(int i2 = (int)(Math.pow(10,  fractPart1Length)- 1d); i2 > 0; i2--){
-                   if (minVal >=  Math.abs((double)i2/(double)i - decPart)) {
-                      currDenom = i;
-                      currNeum = i2;
-                      minVal = Math.abs((double)i2/(double)i  - decPart);
-                   }
-                }
-             }
-             NumberFormat neumFormatter = new DecimalFormat(fractParts[0]);
-             NumberFormat denomFormatter = new DecimalFormat(fractParts[1]);
-             if (parts.length == 2) {
-                NumberFormat wholeFormatter = new DecimalFormat(parts[0]);
-                String result = wholeFormatter.format(wholePart) + " " + neumFormatter.format(currNeum) + "/" + denomFormatter.format(currDenom);
-                return result;
-             } else {
-                String result = neumFormatter.format(currNeum + (currDenom * wholePart)) + "/" + denomFormatter.format(currDenom);
-                return result;
-             }
-          } else {
-             throw new IllegalArgumentException("Fraction must have 2 parts, found " + fractParts.length + " for fraction format " + this.str);
-          }
-       }
-       
-       private int countHashes(String format) {
-          int count = 0;
-          for (int i=format.length()-1; i >= 0; i--) {
-                  if (format.charAt(i) == '#') {
-                          count++;
-                  }
-          }
-          return count;
-       }
-
-       public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
-          return toAppendTo.append(format((Number)obj));
-       }
-
-       public Object parseObject(String source, ParsePosition pos) {
-          throw new NotImplementedException("Reverse parsing not supported");
-       }
-    }
 
+    
+    
     /**
      * Format class that does nothing and always returns a constant string.
      *
diff --git a/src/java/org/apache/poi/ss/usermodel/FractionFormat.java b/src/java/org/apache/poi/ss/usermodel/FractionFormat.java
new file mode 100644 (file)
index 0000000..1522e7a
--- /dev/null
@@ -0,0 +1,271 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package org.apache.poi.ss.usermodel;\r
+import java.text.FieldPosition;\r
+import java.text.Format;\r
+import java.text.ParsePosition;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.apache.poi.ss.formula.eval.NotImplementedException;\r
+\r
+/**\r
+ * <p>Format class that handles Excel style fractions, such as "# #/#" and "#/###"</p>\r
+ * \r
+ * <p>As of this writing, this is still not 100% accurate, but it does a reasonable job\r
+ * of trying to mimic Excel's fraction calculations.  It does not currently\r
+ * maintain Excel's spacing.</p>\r
+ * \r
+ * <p>This class relies on a method lifted nearly verbatim from org.apache.math.fraction.\r
+ *  If further uses for Commons Math are found, we will consider adding it as a dependency.\r
+ *  For now, we have in-lined the one method to keep things simple.</p>\r
+ */\r
+/* One question remains...is the value of epsilon in calcFractionMaxDenom reasonable? */\r
+@SuppressWarnings("serial")\r
+public class FractionFormat extends Format {\r
+    private final static Pattern DENOM_FORMAT_PATTERN = Pattern.compile("(?:(#+)|(\\d+))");\r
+\r
+    //this was chosen to match the earlier limitation of max denom power\r
+    //it can be expanded to get closer to Excel's calculations\r
+    //with custom formats # #/#########\r
+    //but as of this writing, the numerators and denominators\r
+    //with formats of that nature on very small values were quite\r
+    //far from Excel's calculations\r
+    private final static int MAX_DENOM_POW = 4;\r
+\r
+    //there are two options:\r
+    //a) an exact denominator is specified in the formatString\r
+    //b) the maximum denominator can be calculated from the formatString\r
+    private final int exactDenom;\r
+    private final int maxDenom;\r
+\r
+    private final String wholePartFormatString;\r
+    /**\r
+     * Single parameter ctor\r
+     * @param denomFormatString The format string for the denominator\r
+     */\r
+    public FractionFormat(String wholePartFormatString, String denomFormatString) {\r
+        this.wholePartFormatString = wholePartFormatString;\r
+        //init exactDenom and maxDenom\r
+        Matcher m = DENOM_FORMAT_PATTERN.matcher(denomFormatString);\r
+        int tmpExact = -1;\r
+        int tmpMax = -1;\r
+        if (m.find()){\r
+            if (m.group(2) != null){\r
+                try{\r
+                    tmpExact = Integer.parseInt(m.group(2));\r
+                    //if the denom is 0, fall back to the default: tmpExact=100\r
+                    \r
+                    if (tmpExact == 0){\r
+                        tmpExact = -1;\r
+                    }\r
+                } catch (NumberFormatException e){\r
+                    //should never happen\r
+                }\r
+            } else if (m.group(1) != null) {\r
+                int len = m.group(1).length();\r
+                len = len > MAX_DENOM_POW ? MAX_DENOM_POW : len;\r
+                tmpMax = (int)Math.pow(10, len);\r
+            } else {\r
+                tmpExact = 100;\r
+            }\r
+        }\r
+        if (tmpExact <= 0 && tmpMax <= 0){\r
+            //use 100 as the default denom if something went horribly wrong\r
+            tmpExact = 100;\r
+        }\r
+        exactDenom = tmpExact;\r
+        maxDenom = tmpMax;\r
+    }\r
+\r
+    public String format(Number num) {\r
+\r
+        double doubleValue = num.doubleValue();\r
+        \r
+        boolean isNeg = (doubleValue < 0.0f) ? true : false;\r
+        double absDoubleValue = Math.abs(doubleValue);\r
+        \r
+        double wholePart = Math.floor(absDoubleValue);\r
+        double decPart = absDoubleValue - wholePart;\r
+        if (wholePart + decPart == 0) {\r
+            return "0";\r
+        }\r
+        \r
+        //if the absolute value is smaller than 1 over the exact or maxDenom\r
+        //you can stop here and return "0"\r
+        if (absDoubleValue < (1/Math.max(exactDenom,  maxDenom))){\r
+            return "0";\r
+        }\r
+        \r
+        //this is necessary to prevent overflow in the maxDenom calculation\r
+        //stink1\r
+        if (wholePart+(int)decPart == wholePart+decPart){\r
+            \r
+            StringBuilder sb = new StringBuilder();\r
+            if (isNeg){\r
+                sb.append("-");\r
+            }\r
+            sb.append(Integer.toString((int)wholePart));\r
+            return sb.toString();\r
+        }\r
+        \r
+        SimpleFraction fract = null;\r
+        try{\r
+            //this should be the case because of the constructor\r
+            if (exactDenom > 0){\r
+                fract = calcFractionExactDenom(decPart, exactDenom);\r
+            } else {\r
+                fract = calcFractionMaxDenom(decPart, maxDenom);\r
+            }\r
+        } catch (SimpleFractionException e){\r
+            e.printStackTrace();\r
+            return Double.toString(doubleValue);\r
+        }\r
+\r
+        StringBuilder sb = new StringBuilder();\r
+        \r
+        //now format the results\r
+        if (isNeg){\r
+            sb.append("-");\r
+        }\r
+        \r
+        //if whole part has to go into the numerator\r
+        if ("".equals(wholePartFormatString)){\r
+            int trueNum = (fract.getDenominator()*(int)wholePart)+fract.getNumerator();\r
+            sb.append(trueNum).append("/").append(fract.getDenominator());\r
+            return sb.toString();\r
+        }\r
+        \r
+        \r
+        //short circuit if fraction is 0 or 1\r
+        if (fract.getNumerator() == 0){\r
+            sb.append(Integer.toString((int)wholePart));\r
+            return sb.toString();\r
+        } else if (fract.getNumerator() == fract.getDenominator()){\r
+            sb.append(Integer.toString((int)wholePart+1));\r
+            return sb.toString();\r
+        }\r
+       //as mentioned above, this ignores the exact space formatting in Excel\r
+        if (wholePart > 0){\r
+            sb.append(Integer.toString((int)wholePart)).append(" ");\r
+        }\r
+        sb.append(fract.getNumerator()).append("/").append(fract.getDenominator());\r
+        return sb.toString();\r
+    }\r
+\r
+    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {\r
+        return toAppendTo.append(format((Number)obj));\r
+    }\r
+\r
+    public Object parseObject(String source, ParsePosition pos) {\r
+        throw new NotImplementedException("Reverse parsing not supported");\r
+    }\r
+\r
+    private SimpleFraction calcFractionMaxDenom(double value, int maxDenominator) \r
+            throws SimpleFractionException{\r
+        /*\r
+         * Lifted wholesale from org.apache.math.fraction.Fraction 2.2\r
+         */\r
+        double epsilon = 0.000000000001f;\r
+        int maxIterations = 100;\r
+        long overflow = Integer.MAX_VALUE;\r
+        double r0 = value;\r
+        long a0 = (long)Math.floor(r0);\r
+        if (Math.abs(a0) > overflow) {\r
+            throw new SimpleFractionException(\r
+                    String.format("value > Integer.MAX_VALUE: %d.", a0));\r
+        }\r
+\r
+        // check for (almost) integer arguments, which should not go\r
+        // to iterations.\r
+        if (Math.abs(a0 - value) < epsilon) {\r
+            return new SimpleFraction((int) a0, 1);\r
+        }\r
+\r
+        long p0 = 1;\r
+        long q0 = 0;\r
+        long p1 = a0;\r
+        long q1 = 1;\r
+\r
+        long p2 = 0;\r
+        long q2 = 1;\r
+\r
+        int n = 0;\r
+        boolean stop = false;\r
+        do {\r
+            ++n;\r
+            double r1 = 1.0 / (r0 - a0);\r
+            long a1 = (long)Math.floor(r1);\r
+            p2 = (a1 * p1) + p0;\r
+            q2 = (a1 * q1) + q0;\r
+            if ((Math.abs(p2) > overflow) || (Math.abs(q2) > overflow)) {\r
+                throw new SimpleFractionException(\r
+                        String.format("Greater than overflow in loop %f, %d, %d", value, p2, q2));\r
+            }\r
+\r
+            double convergent = (double)p2 / (double)q2;\r
+            if (n < maxIterations && Math.abs(convergent - value) > epsilon && q2 < maxDenominator) {\r
+                p0 = p1;\r
+                p1 = p2;\r
+                q0 = q1;\r
+                q1 = q2;\r
+                a0 = a1;\r
+                r0 = r1;\r
+            } else {\r
+                stop = true;\r
+            }\r
+        } while (!stop);\r
+\r
+        if (n >= maxIterations) {\r
+            throw new SimpleFractionException("n greater than max iterations " + value + " : " + maxIterations);\r
+        }\r
+\r
+        if (q2 < maxDenominator) {\r
+            return new SimpleFraction((int) p2, (int) q2);\r
+        } else {\r
+            return new SimpleFraction((int) p1, (int) q1);\r
+        }\r
+    }\r
+\r
+    private SimpleFraction calcFractionExactDenom(double val, int exactDenom){\r
+        int num =  (int)Math.round(val*(double)exactDenom);\r
+        return new SimpleFraction(num,exactDenom);\r
+    }\r
+\r
+    private class SimpleFraction {\r
+        private final int num;\r
+        private final int denom;\r
+\r
+        public SimpleFraction(int num, int denom) {\r
+            this.num = num;\r
+            this.denom = denom;\r
+        }\r
+\r
+        public int getNumerator() {\r
+            return num;\r
+        }\r
+        public int getDenominator() {\r
+            return denom;\r
+        }\r
+    }\r
+    private class SimpleFractionException extends Throwable{\r
+        private SimpleFractionException(String message){\r
+            super(message);\r
+        }\r
+    }\r
+}\r
index c6233fcf39afd05c0380c4df2fbc805b1f968566..6dcd6ebebab7fced1a0dfbe1a60a4a3228913d64 100644 (file)
@@ -229,13 +229,25 @@ public class TestDataFormatter extends TestCase {
        assertEquals("321 321/1000",  dfUS.formatRawCellContents(321.321, -1, "# #/##########"));
        
        // Not a valid fraction formats (too many #/# or ?/?) - hence the strange expected results
-       assertEquals("321 / ?/?",   dfUS.formatRawCellContents(321.321, -1, "# #/# ?/?"));
+       
+/*       assertEquals("321 / ?/?",   dfUS.formatRawCellContents(321.321, -1, "# #/# ?/?"));
        assertEquals("321 / /",     dfUS.formatRawCellContents(321.321, -1, "# #/# #/#"));
        assertEquals("321 ?/? ?/?",   dfUS.formatRawCellContents(321.321, -1, "# ?/? ?/?"));
        assertEquals("321 ?/? / /",   dfUS.formatRawCellContents(321.321, -1, "# ?/? #/# #/#"));
+*/
+
+       //Bug54686 patch sets default behavior of # #/## if there is a failure to parse
+       assertEquals("321 1/3",   dfUS.formatRawCellContents(321.321, -1, "# #/# ?/?"));
+       assertEquals("321 1/3",     dfUS.formatRawCellContents(321.321, -1, "# #/# #/#"));
+       assertEquals("321 1/3",   dfUS.formatRawCellContents(321.321, -1, "# ?/? ?/?"));
+       assertEquals("321 1/3",   dfUS.formatRawCellContents(321.321, -1, "# ?/? #/# #/#"));
 
        // Where both p and n don't include a fraction, so cannot always be formatted
-       assertEquals("123", dfUS.formatRawCellContents(-123.321, -1, "0 ?/?;0"));
+      // assertEquals("123", dfUS.formatRawCellContents(-123.321, -1, "0 ?/?;0"));
+
+       //Bug54868 patch has a hit on the first string before the ";"
+       assertEquals("-123 1/3", dfUS.formatRawCellContents(-123.321, -1, "0 ?/?;0"));
+
     }
     
     /**
diff --git a/src/testcases/org/apache/poi/ss/usermodel/TestFractionFormat.java b/src/testcases/org/apache/poi/ss/usermodel/TestFractionFormat.java
new file mode 100644 (file)
index 0000000..1db2507
--- /dev/null
@@ -0,0 +1,83 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.usermodel;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStreamReader;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.FractionFormat;
+import org.apache.poi.ss.usermodel.Row;
+
+/**
+ * Tests for the Fraction Formatting part of DataFormatter.
+ * Largely taken from bug #54686
+ */
+public final class TestFractionFormat extends TestCase {
+      public void testSingle() throws Exception {
+        FractionFormat f = new FractionFormat("", "##");
+        double val = 321.321;
+        String ret = f.format(val);
+        assertEquals("26027/81", ret);
+    }
+     
+    public void testTruthFile() throws Exception {
+        File truthFile = HSSFTestDataSamples.getSampleFile("54686_fraction_formats.txt");
+        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(truthFile)));
+        Workbook wb = HSSFTestDataSamples.openSampleWorkbook("54686_fraction_formats.xls");
+        Sheet sheet = wb.getSheetAt(0);
+        DataFormatter formatter = new DataFormatter();
+        FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
+
+        // Skip over the header row
+        String truthLine = reader.readLine();
+        String[] headers = truthLine.split("\t");
+        truthLine = reader.readLine();
+
+        for (int i = 1; i < sheet.getLastRowNum() && truthLine != null; i++){
+            Row r = sheet.getRow(i);
+            String[] truths = truthLine.split("\t");
+            // Intentionally ignore the last column (tika-1132), for now
+            for (short j = 3; j < 12; j++){
+                Cell cell = r.getCell(j, Row.CREATE_NULL_AS_BLANK);
+                String formatted = clean(formatter.formatCellValue(cell, evaluator));
+                if (truths.length <= j){
+                    continue;
+                }
+
+                String truth = clean(truths[j]);
+                String testKey = truths[0]+":"+truths[1]+":"+headers[j];
+                assertEquals(testKey, truth, formatted);
+            }
+            truthLine = reader.readLine();
+        }
+        reader.close();
+    }
+
+    private String clean(String s){
+        s = s.trim().replaceAll(" +",  " ").replaceAll("- +", "-");
+        return s;
+    }
+}
diff --git a/test-data/spreadsheet/54686_fraction_formats.txt b/test-data/spreadsheet/54686_fraction_formats.txt
new file mode 100644 (file)
index 0000000..0de773e
--- /dev/null
@@ -0,0 +1,374 @@
+Numerator      Denominator     Double  1Digit  2Digit  3Digit  Half    Quarter Eight   Sixteenth       Tenth   100th   Tika-1132\r
+4051   8750153 0.000462963     0       0       0               0       0       0       0       0       0                4051/8750153  \r
+-105   100     -1.05   -1      -1  1/20        -1   1/20       -1      -1      -1      -1  1/16        -1 1/10 -1  5/100       -1  1/20       \r
+-104   100     -1.04   -1      -1  1/25        -1   1/25       -1      -1      -1      -1  1/16        -1      -1  4/100       -1  1/25       \r
+-103   100     -1.03   -1      -1  1/33        -1   3/100      -1      -1      -1      -1              -1      -1  3/100       -1  3/100      \r
+-102   100     -1.02   -1      -1  1/50        -1   1/50       -1      -1      -1      -1              -1      -1  2/100       -1  1/50       \r
+-101   100     -1.01   -1      -1  1/99        -1   1/100      -1      -1      -1      -1              -1      -1  1/100       -1  1/100      \r
+-100   100     -1      -1      -1              -1              -1      -1      -1      -1              -1      -1              -1             \r
+-99    100     -0.99   -1      - 98/99 -  99/100       -1      -1      -1      -1              -1      - 99/100        - 99/100      \r
+-98    100     -0.98   -1      - 49/50 -  49/50        -1      -1      -1      -1              -1      - 98/100        - 49/50       \r
+-97    100     -0.97   -1      - 32/33 -  97/100       -1      -1      -1      -1              -1      - 97/100        - 97/100      \r
+-96    100     -0.96   -1      - 24/25 -  24/25        -1      -1      -1      - 15/16 -1      - 96/100        - 24/25       \r
+-95    100     -0.95   -1      - 19/20 -  19/20        -1      -1      -1      - 15/16 -1      - 95/100        - 19/20       \r
+-94    100     -0.94   -1      - 47/50 -  47/50        -1      -1      -1      - 15/16 - 9/10  - 94/100        - 47/50       \r
+-93    100     -0.93   -1      - 40/43 -  93/100       -1      -1      - 7/8   - 15/16 - 9/10  - 93/100        - 93/100      \r
+-92    100     -0.92   -1      - 23/25 -  23/25        -1      -1      - 7/8   - 15/16 - 9/10  - 92/100        - 23/25       \r
+-91    100     -0.91   -1      - 81/89 -  91/100       -1      -1      - 7/8   - 15/16 - 9/10  - 91/100        - 91/100      \r
+-90    100     -0.9    - 8/9   -  9/10 -   9/10        -1      -1      - 7/8   - 14/16 - 9/10  - 90/100        -  9/10       \r
+-89    100     -0.89   - 8/9   -  8/9  -  89/100       -1      -1      - 7/8   - 14/16 - 9/10  - 89/100        - 89/100      \r
+-88    100     -0.88   - 7/8   - 22/25 -  22/25        -1      -1      - 7/8   - 14/16 - 9/10  - 88/100        - 22/25       \r
+-87    100     -0.87   - 7/8   - 67/77 -  87/100       -1      - 3/4   - 7/8   - 14/16 - 9/10  - 87/100        - 87/100      \r
+-86    100     -0.86   - 6/7   - 43/50 -  43/50        -1      - 3/4   - 7/8   - 14/16 - 9/10  - 86/100        - 43/50       \r
+-85    100     -0.85   - 6/7   - 17/20 -  17/20        -1      - 3/4   - 7/8   - 14/16 - 9/10  - 85/100        - 17/20       \r
+-84    100     -0.84   - 5/6   - 21/25 -  21/25        -1      - 3/4   - 7/8   - 13/16 - 8/10  - 84/100        - 21/25       \r
+-83    100     -0.83   - 5/6   - 39/47 -  83/100       -1      - 3/4   - 7/8   - 13/16 - 8/10  - 83/100        - 83/100      \r
+-82    100     -0.82   - 5/6   - 41/50 -  41/50        -1      - 3/4   - 7/8   - 13/16 - 8/10  - 82/100        - 41/50       \r
+-81    100     -0.81   - 4/5   - 64/79 -  81/100       -1      - 3/4   - 6/8   - 13/16 - 8/10  - 81/100        - 81/100      \r
+-80    100     -0.8    - 4/5   -  4/5  -   4/5         -1      - 3/4   - 6/8   - 13/16 - 8/10  - 80/100        -  4/5        \r
+-79    100     -0.79   - 4/5   - 64/81 -  79/100       -1      - 3/4   - 6/8   - 13/16 - 8/10  - 79/100        - 79/100      \r
+-78    100     -0.78   - 7/9   - 39/50 -  39/50        -1      - 3/4   - 6/8   - 12/16 - 8/10  - 78/100        - 39/50       \r
+-77    100     -0.77   - 7/9   - 67/87 -  77/100       -1      - 3/4   - 6/8   - 12/16 - 8/10  - 77/100        - 77/100      \r
+-76    100     -0.76   - 3/4   - 19/25 -  19/25        -1      - 3/4   - 6/8   - 12/16 - 8/10  - 76/100        - 19/25       \r
+-75    100     -0.75   - 3/4   -  3/4  -   3/4         -1      - 3/4   - 6/8   - 12/16 - 8/10  - 75/100        -  3/4        \r
+-74    100     -0.74   - 3/4   - 37/50 -  37/50        - 1/2   - 3/4   - 6/8   - 12/16 - 7/10  - 74/100        - 37/50       \r
+-73    100     -0.73   - 3/4   - 46/63 -  73/100       - 1/2   - 3/4   - 6/8   - 12/16 - 7/10  - 73/100        - 73/100      \r
+-72    100     -0.72   - 5/7   - 18/25 -  18/25        - 1/2   - 3/4   - 6/8   - 12/16 - 7/10  - 72/100        - 18/25       \r
+-71    100     -0.71   - 5/7   - 22/31 -  71/100       - 1/2   - 3/4   - 6/8   - 11/16 - 7/10  - 71/100        - 71/100      \r
+-70    100     -0.7    - 2/3   -  7/10 -   7/10        - 1/2   - 3/4   - 6/8   - 11/16 - 7/10  - 70/100        -  7/10       \r
+-69    100     -0.69   - 2/3   - 20/29 -  69/100       - 1/2   - 3/4   - 6/8   - 11/16 - 7/10  - 69/100        - 69/100      \r
+-68    100     -0.68   - 2/3   - 17/25 -  17/25        - 1/2   - 3/4   - 5/8   - 11/16 - 7/10  - 68/100        - 17/25       \r
+-67    100     -0.67   - 2/3   - 65/97 -  67/100       - 1/2   - 3/4   - 5/8   - 11/16 - 7/10  - 67/100        - 67/100      \r
+-66    100     -0.66   - 2/3   - 33/50 -  33/50        - 1/2   - 3/4   - 5/8   - 11/16 - 7/10  - 66/100        - 33/50       \r
+-65    100     -0.65   - 2/3   - 13/20 -  13/20        - 1/2   - 3/4   - 5/8   - 10/16 - 7/10  - 65/100        - 13/20       \r
+-64    100     -0.64   - 2/3   - 16/25 -  16/25        - 1/2   - 3/4   - 5/8   - 10/16 - 6/10  - 64/100        - 16/25       \r
+-63    100     -0.63   - 5/8   - 46/73 -  63/100       - 1/2   - 3/4   - 5/8   - 10/16 - 6/10  - 63/100        - 63/100      \r
+-62    100     -0.62   - 5/8   - 31/50 -  31/50        - 1/2   - 2/4   - 5/8   - 10/16 - 6/10  - 62/100        - 31/50       \r
+-61    100     -0.61   - 3/5   - 36/59 -  61/100       - 1/2   - 2/4   - 5/8   - 10/16 - 6/10  - 61/100        - 61/100      \r
+-60    100     -0.6    - 3/5   -  3/5  -   3/5         - 1/2   - 2/4   - 5/8   - 10/16 - 6/10  - 60/100        -  3/5        \r
+-59    100     -0.59   - 3/5   - 23/39 -  59/100       - 1/2   - 2/4   - 5/8   -  9/16 - 6/10  - 59/100        - 59/100      \r
+-58    100     -0.58   - 4/7   - 29/50 -  29/50        - 1/2   - 2/4   - 5/8   -  9/16 - 6/10  - 58/100        - 29/50       \r
+-57    100     -0.57   - 4/7   - 53/93 -  57/100       - 1/2   - 2/4   - 5/8   -  9/16 - 6/10  - 57/100        - 57/100      \r
+-56    100     -0.56   - 5/9   - 14/25 -  14/25        - 1/2   - 2/4   - 4/8   -  9/16 - 6/10  - 56/100        - 14/25       \r
+-55    100     -0.55   - 5/9   - 11/20 -  11/20        - 1/2   - 2/4   - 4/8   -  9/16 - 6/10  - 55/100        - 11/20       \r
+-54    100     -0.54   - 1/2   - 27/50 -  27/50        - 1/2   - 2/4   - 4/8   -  9/16 - 5/10  - 54/100        - 27/50       \r
+-53    100     -0.53   - 1/2   - 44/83 -  53/100       - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 53/100        - 53/100      \r
+-52    100     -0.52   - 1/2   - 13/25 -  13/25        - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 52/100        - 13/25       \r
+-51    100     -0.51   - 1/2   - 25/49 -  51/100       - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 51/100        - 51/100      \r
+-50    100     -0.5    - 1/2   -  1/2  -   1/2         - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 50/100        -  1/2        \r
+-49    100     -0.49   - 1/2   - 24/49 -  49/100       - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 49/100        - 49/100      \r
+-48    100     -0.48   - 1/2   - 12/25 -  12/25        - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 48/100        - 12/25       \r
+-47    100     -0.47   - 1/2   -  8/17 -  47/100       - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 47/100        - 47/100      \r
+-46    100     -0.46   - 1/2   - 23/50 -  23/50        - 1/2   - 2/4   - 4/8   -  7/16 - 5/10  - 46/100        - 23/50       \r
+-45    100     -0.45   - 4/9   -  9/20 -   9/20        - 1/2   - 2/4   - 4/8   -  7/16 - 5/10  - 45/100        -  9/20       \r
+-44    100     -0.44   - 4/9   - 11/25 -  11/25        - 1/2   - 2/4   - 4/8   -  7/16 - 4/10  - 44/100        - 11/25       \r
+-43    100     -0.43   - 3/7   -  3/7  -  43/100       - 1/2   - 2/4   - 3/8   -  7/16 - 4/10  - 43/100        - 43/100      \r
+-42    100     -0.42   - 3/7   - 21/50 -  21/50        - 1/2   - 2/4   - 3/8   -  7/16 - 4/10  - 42/100        - 21/50       \r
+-41    100     -0.41   - 2/5   - 16/39 -  41/100       - 1/2   - 2/4   - 3/8   -  7/16 - 4/10  - 41/100        - 41/100      \r
+-40    100     -0.4    - 2/5   -  2/5  -   2/5         - 1/2   - 2/4   - 3/8   -  6/16 - 4/10  - 40/100        -  2/5        \r
+-39    100     -0.39   - 2/5   - 16/41 -  39/100       - 1/2   - 2/4   - 3/8   -  6/16 - 4/10  - 39/100        - 39/100      \r
+-38    100     -0.38   - 3/8   - 19/50 -  19/50        - 1/2   - 2/4   - 3/8   -  6/16 - 4/10  - 38/100        - 19/50       \r
+-37    100     -0.37   - 3/8   - 10/27 -  37/100       - 1/2   - 1/4   - 3/8   -  6/16 - 4/10  - 37/100        - 37/100      \r
+-36    100     -0.36   - 1/3   -  9/25 -   9/25        - 1/2   - 1/4   - 3/8   -  6/16 - 4/10  - 36/100        -  9/25       \r
+-35    100     -0.35   - 1/3   -  7/20 -   7/20        - 1/2   - 1/4   - 3/8   -  6/16 - 4/10  - 35/100        -  7/20       \r
+-34    100     -0.34   - 1/3   - 17/50 -  17/50        - 1/2   - 1/4   - 3/8   -  5/16 - 3/10  - 34/100        - 17/50       \r
+-33    100     -0.33   - 1/3   -  1/3  -  33/100       - 1/2   - 1/4   - 3/8   -  5/16 - 3/10  - 33/100        - 33/100      \r
+-32    100     -0.32   - 1/3   -  8/25 -   8/25        - 1/2   - 1/4   - 3/8   -  5/16 - 3/10  - 32/100        -  8/25       \r
+-31    100     -0.31   - 1/3   - 22/71 -  31/100       - 1/2   - 1/4   - 2/8   -  5/16 - 3/10  - 31/100        - 31/100      \r
+-30    100     -0.3    - 2/7   -  3/10 -   3/10        - 1/2   - 1/4   - 2/8   -  5/16 - 3/10  - 30/100        -  3/10       \r
+-29    100     -0.29   - 2/7   - 20/69 -  29/100       - 1/2   - 1/4   - 2/8   -  5/16 - 3/10  - 29/100        - 29/100      \r
+-28    100     -0.28   - 2/7   -  7/25 -   7/25        - 1/2   - 1/4   - 2/8   -  4/16 - 3/10  - 28/100        -  7/25       \r
+-27    100     -0.27   - 1/4   - 10/37 -  27/100       - 1/2   - 1/4   - 2/8   -  4/16 - 3/10  - 27/100        - 27/100      \r
+-26    100     -0.26   - 1/4   - 13/50 -  13/50        - 1/2   - 1/4   - 2/8   -  4/16 - 3/10  - 26/100        - 13/50       \r
+-25    100     -0.25   - 1/4   -  1/4  -   1/4         - 1/2   - 1/4   - 2/8   -  4/16 - 3/10  - 25/100        -  1/4        \r
+-24    100     -0.24   - 1/4   -  6/25 -   6/25        -0      - 1/4   - 2/8   -  4/16 - 2/10  - 24/100        -  6/25       \r
+-23    100     -0.23   - 2/9   -  3/13 -  23/100       -0      - 1/4   - 2/8   -  4/16 - 2/10  - 23/100        - 23/100      \r
+-22    100     -0.22   - 2/9   - 11/50 -  11/50        -0      - 1/4   - 2/8   -  4/16 - 2/10  - 22/100        - 11/50       \r
+-21    100     -0.21   - 1/5   - 17/81 -  21/100       -0      - 1/4   - 2/8   -  3/16 - 2/10  - 21/100        - 21/100      \r
+-20    100     -0.2    - 1/5   -  1/5  -   1/5         -0      - 1/4   - 2/8   -  3/16 - 2/10  - 20/100        -  1/5        \r
+-19    100     -0.19   - 1/5   - 15/79 -  19/100       -0      - 1/4   - 2/8   -  3/16 - 2/10  - 19/100        - 19/100      \r
+-18    100     -0.18   - 1/6   -  9/50 -   9/50        -0      - 1/4   - 1/8   -  3/16 - 2/10  - 18/100        -  9/50       \r
+-17    100     -0.17   - 1/6   -  8/47 -  17/100       -0      - 1/4   - 1/8   -  3/16 - 2/10  - 17/100        - 17/100      \r
+-16    100     -0.16   - 1/6   -  4/25 -   4/25        -0      - 1/4   - 1/8   -  3/16 - 2/10  - 16/100        -  4/25       \r
+-15    100     -0.15   - 1/7   -  3/20 -   3/20        -0      - 1/4   - 1/8   -  2/16 - 2/10  - 15/100        -  3/20       \r
+-14    100     -0.14   - 1/7   -  7/50 -   7/50        -0      - 1/4   - 1/8   -  2/16 - 1/10  - 14/100        -  7/50       \r
+-13    100     -0.13   - 1/8   -  3/23 -  13/100       -0      - 1/4   - 1/8   -  2/16 - 1/10  - 13/100        - 13/100      \r
+-12    100     -0.12   - 1/8   -  3/25 -   3/25        -0      -0      - 1/8   -  2/16 - 1/10  - 12/100        -  3/25       \r
+-11    100     -0.11   - 1/9   - 10/91 -  11/100       -0      -0      - 1/8   -  2/16 - 1/10  - 11/100        - 11/100      \r
+-10    100     -0.1    -0      -  1/10 -   1/10        -0      -0      - 1/8   -  2/16 - 1/10  - 10/100        -  1/10       \r
+-9     100     -0.09   -0      -  1/11 -   9/100       -0      -0      - 1/8   -  1/16 - 1/10  -  9/100        -  9/100      \r
+-8     100     -0.08   -0      -  2/25 -   2/25        -0      -0      - 1/8   -  1/16 - 1/10  -  8/100        -  2/25       \r
+-7     100     -0.07   -0      -  4/57 -   7/100       -0      -0      - 1/8   -  1/16 - 1/10  -  7/100        -  7/100      \r
+-6     100     -0.06   -0      -  3/50 -   3/50        -0      -0      -0      -  1/16 - 1/10  -  6/100        -  3/50       \r
+-5     100     -0.05   -0      -  1/20 -   1/20        -0      -0      -0      -  1/16 - 1/10  -  5/100        -  1/20       \r
+-4     100     -0.04   -0      -  1/25 -   1/25        -0      -0      -0      -  1/16 -0      -  4/100        -  1/25       \r
+-3     100     -0.03   -0      -  2/67 -   3/100       -0      -0      -0      -0              -0      -  3/100        -  3/100      \r
+-2     100     -0.02   -0      -  1/50 -   1/50        -0      -0      -0      -0              -0      -  2/100        -  1/50       \r
+-1     100     -0.01   -0      -0              -   1/100       -0      -0      -0      -0              -0      -  1/100        -  1/100      \r
+0      100     0       0       0       0               0       0       0       0       0       0               0             \r
+1      100     0.01    0       0          1/100        0       0       0       0       0         1/100   1/100      \r
+2      100     0.02    0         1/50     1/50         0       0       0       0       0         2/100   1/50       \r
+3      100     0.03    0         2/67     3/100        0       0       0       0       0         3/100   3/100      \r
+4      100     0.04    0         1/25     1/25         0       0       0         1/16  0         4/100   1/25       \r
+5      100     0.05    0         1/20     1/20         0       0       0         1/16   1/10     5/100   1/20       \r
+6      100     0.06    0         3/50     3/50         0       0       0         1/16   1/10     6/100   3/50       \r
+7      100     0.07    0         4/57     7/100        0       0        1/8      1/16   1/10     7/100   7/100      \r
+8      100     0.08    0         2/25     2/25         0       0        1/8      1/16   1/10     8/100   2/25       \r
+9      100     0.09    0         1/11     9/100        0       0        1/8      1/16   1/10     9/100   9/100      \r
+10     100     0.1     0         1/10     1/10         0       0        1/8      2/16   1/10    10/100   1/10       \r
+11     100     0.11     1/9     10/91    11/100        0       0        1/8      2/16   1/10    11/100  11/100      \r
+12     100     0.12     1/8      3/25     3/25         0       0        1/8      2/16   1/10    12/100   3/25       \r
+13     100     0.13     1/8      3/23    13/100        0        1/4     1/8      2/16   1/10    13/100  13/100      \r
+14     100     0.14     1/7      7/50     7/50         0        1/4     1/8      2/16   1/10    14/100   7/50       \r
+15     100     0.15     1/7      3/20     3/20         0        1/4     1/8      2/16   2/10    15/100   3/20       \r
+16     100     0.16     1/6      4/25     4/25         0        1/4     1/8      3/16   2/10    16/100   4/25       \r
+17     100     0.17     1/6      8/47    17/100        0        1/4     1/8      3/16   2/10    17/100  17/100      \r
+18     100     0.18     1/6      9/50     9/50         0        1/4     1/8      3/16   2/10    18/100   9/50       \r
+19     100     0.19     1/5     15/79    19/100        0        1/4     2/8      3/16   2/10    19/100  19/100      \r
+20     100     0.2      1/5      1/5      1/5          0        1/4     2/8      3/16   2/10    20/100   1/5        \r
+21     100     0.21     1/5     17/81    21/100        0        1/4     2/8      3/16   2/10    21/100  21/100      \r
+22     100     0.22     2/9     11/50    11/50         0        1/4     2/8      4/16   2/10    22/100  11/50       \r
+23     100     0.23     2/9      3/13    23/100        0        1/4     2/8      4/16   2/10    23/100  23/100      \r
+24     100     0.24     1/4      6/25     6/25         0        1/4     2/8      4/16   2/10    24/100   6/25       \r
+25     100     0.25     1/4      1/4      1/4           1/2     1/4     2/8      4/16   3/10    25/100   1/4        \r
+26     100     0.26     1/4     13/50    13/50          1/2     1/4     2/8      4/16   3/10    26/100  13/50       \r
+27     100     0.27     1/4     10/37    27/100         1/2     1/4     2/8      4/16   3/10    27/100  27/100      \r
+28     100     0.28     2/7      7/25     7/25          1/2     1/4     2/8      4/16   3/10    28/100   7/25       \r
+29     100     0.29     2/7     20/69    29/100         1/2     1/4     2/8      5/16   3/10    29/100  29/100      \r
+30     100     0.3      2/7      3/10     3/10          1/2     1/4     2/8      5/16   3/10    30/100   3/10       \r
+31     100     0.31     1/3     22/71    31/100         1/2     1/4     2/8      5/16   3/10    31/100  31/100      \r
+32     100     0.32     1/3      8/25     8/25          1/2     1/4     3/8      5/16   3/10    32/100   8/25       \r
+33     100     0.33     1/3      1/3     33/100         1/2     1/4     3/8      5/16   3/10    33/100  33/100      \r
+34     100     0.34     1/3     17/50    17/50          1/2     1/4     3/8      5/16   3/10    34/100  17/50       \r
+35     100     0.35     1/3      7/20     7/20          1/2     1/4     3/8      6/16   4/10    35/100   7/20       \r
+36     100     0.36     1/3      9/25     9/25          1/2     1/4     3/8      6/16   4/10    36/100   9/25       \r
+37     100     0.37     3/8     10/27    37/100         1/2     1/4     3/8      6/16   4/10    37/100  37/100      \r
+38     100     0.38     3/8     19/50    19/50          1/2     2/4     3/8      6/16   4/10    38/100  19/50       \r
+39     100     0.39     2/5     16/41    39/100         1/2     2/4     3/8      6/16   4/10    39/100  39/100      \r
+40     100     0.4      2/5      2/5      2/5           1/2     2/4     3/8      6/16   4/10    40/100   2/5        \r
+41     100     0.41     2/5     16/39    41/100         1/2     2/4     3/8      7/16   4/10    41/100  41/100      \r
+42     100     0.42     3/7     21/50    21/50          1/2     2/4     3/8      7/16   4/10    42/100  21/50       \r
+43     100     0.43     3/7      3/7     43/100         1/2     2/4     3/8      7/16   4/10    43/100  43/100      \r
+44     100     0.44     4/9     11/25    11/25          1/2     2/4     4/8      7/16   4/10    44/100  11/25       \r
+45     100     0.45     4/9      9/20     9/20          1/2     2/4     4/8      7/16   5/10    45/100   9/20       \r
+46     100     0.46     1/2     23/50    23/50          1/2     2/4     4/8      7/16   5/10    46/100  23/50       \r
+47     100     0.47     1/2      8/17    47/100         1/2     2/4     4/8      8/16   5/10    47/100  47/100      \r
+48     100     0.48     1/2     12/25    12/25          1/2     2/4     4/8      8/16   5/10    48/100  12/25       \r
+49     100     0.49     1/2     24/49    49/100         1/2     2/4     4/8      8/16   5/10    49/100  49/100      \r
+50     100     0.5      1/2      1/2      1/2           1/2     2/4     4/8      8/16   5/10    50/100   1/2        \r
+51     100     0.51     1/2     25/49    51/100         1/2     2/4     4/8      8/16   5/10    51/100  51/100      \r
+52     100     0.52     1/2     13/25    13/25          1/2     2/4     4/8      8/16   5/10    52/100  13/25       \r
+53     100     0.53     1/2     44/83    53/100         1/2     2/4     4/8      8/16   5/10    53/100  53/100      \r
+54     100     0.54     1/2     27/50    27/50          1/2     2/4     4/8      9/16   5/10    54/100  27/50       \r
+55     100     0.55     5/9     11/20    11/20          1/2     2/4     4/8      9/16   6/10    55/100  11/20       \r
+56     100     0.56     5/9     14/25    14/25          1/2     2/4     4/8      9/16   6/10    56/100  14/25       \r
+57     100     0.57     4/7     53/93    57/100         1/2     2/4     5/8      9/16   6/10    57/100  57/100      \r
+58     100     0.58     4/7     29/50    29/50          1/2     2/4     5/8      9/16   6/10    58/100  29/50       \r
+59     100     0.59     3/5     23/39    59/100         1/2     2/4     5/8      9/16   6/10    59/100  59/100      \r
+60     100     0.6      3/5      3/5      3/5           1/2     2/4     5/8     10/16   6/10    60/100   3/5        \r
+61     100     0.61     3/5     36/59    61/100         1/2     2/4     5/8     10/16   6/10    61/100  61/100      \r
+62     100     0.62     5/8     31/50    31/50          1/2     2/4     5/8     10/16   6/10    62/100  31/50       \r
+63     100     0.63     5/8     46/73    63/100         1/2     3/4     5/8     10/16   6/10    63/100  63/100      \r
+64     100     0.64     2/3     16/25    16/25          1/2     3/4     5/8     10/16   6/10    64/100  16/25       \r
+65     100     0.65     2/3     13/20    13/20          1/2     3/4     5/8     10/16   7/10    65/100  13/20       \r
+66     100     0.66     2/3     33/50    33/50          1/2     3/4     5/8     11/16   7/10    66/100  33/50       \r
+67     100     0.67     2/3     65/97    67/100         1/2     3/4     5/8     11/16   7/10    67/100  67/100      \r
+68     100     0.68     2/3     17/25    17/25          1/2     3/4     5/8     11/16   7/10    68/100  17/25       \r
+69     100     0.69     2/3     20/29    69/100         1/2     3/4     6/8     11/16   7/10    69/100  69/100      \r
+70     100     0.7      2/3      7/10     7/10          1/2     3/4     6/8     11/16   7/10    70/100   7/10       \r
+71     100     0.71     5/7     22/31    71/100         1/2     3/4     6/8     11/16   7/10    71/100  71/100      \r
+72     100     0.72     5/7     18/25    18/25          1/2     3/4     6/8     12/16   7/10    72/100  18/25       \r
+73     100     0.73     3/4     46/63    73/100         1/2     3/4     6/8     12/16   7/10    73/100  73/100      \r
+74     100     0.74     3/4     37/50    37/50          1/2     3/4     6/8     12/16   7/10    74/100  37/50       \r
+75     100     0.75     3/4      3/4      3/4          1        3/4     6/8     12/16   8/10    75/100   3/4        \r
+76     100     0.76     3/4     19/25    19/25         1        3/4     6/8     12/16   8/10    76/100  19/25       \r
+77     100     0.77     7/9     67/87    77/100        1        3/4     6/8     12/16   8/10    77/100  77/100      \r
+78     100     0.78     7/9     39/50    39/50         1        3/4     6/8     12/16   8/10    78/100  39/50       \r
+79     100     0.79     4/5     64/81    79/100        1        3/4     6/8     13/16   8/10    79/100  79/100      \r
+80     100     0.8      4/5      4/5      4/5          1        3/4     6/8     13/16   8/10    80/100   4/5        \r
+81     100     0.81     4/5     64/79    81/100        1        3/4     6/8     13/16   8/10    81/100  81/100      \r
+82     100     0.82     5/6     41/50    41/50         1        3/4     7/8     13/16   8/10    82/100  41/50       \r
+83     100     0.83     5/6     39/47    83/100        1        3/4     7/8     13/16   8/10    83/100  83/100      \r
+84     100     0.84     5/6     21/25    21/25         1        3/4     7/8     13/16   8/10    84/100  21/25       \r
+85     100     0.85     6/7     17/20    17/20         1        3/4     7/8     14/16   9/10    85/100  17/20       \r
+86     100     0.86     6/7     43/50    43/50         1        3/4     7/8     14/16   9/10    86/100  43/50       \r
+87     100     0.87     7/8     67/77    87/100        1        3/4     7/8     14/16   9/10    87/100  87/100      \r
+88     100     0.88     7/8     22/25    22/25         1       1        7/8     14/16   9/10    88/100  22/25       \r
+89     100     0.89     8/9      8/9     89/100        1       1        7/8     14/16   9/10    89/100  89/100      \r
+90     100     0.9      8/9      9/10     9/10         1       1        7/8     14/16   9/10    90/100   9/10       \r
+91     100     0.91    1        81/89    91/100        1       1        7/8     15/16   9/10    91/100  91/100      \r
+92     100     0.92    1        23/25    23/25         1       1        7/8     15/16   9/10    92/100  23/25       \r
+93     100     0.93    1        40/43    93/100        1       1        7/8     15/16   9/10    93/100  93/100      \r
+94     100     0.94    1        47/50    47/50         1       1       1        15/16   9/10    94/100  47/50       \r
+95     100     0.95    1        19/20    19/20         1       1       1        15/16  1        95/100  19/20       \r
+96     100     0.96    1        24/25    24/25         1       1       1        15/16  1        96/100  24/25       \r
+97     100     0.97    1        32/33    97/100        1       1       1       1       1        97/100  97/100      \r
+98     100     0.98    1        49/50    49/50         1       1       1       1       1        98/100  49/50       \r
+99     100     0.99    1        98/99    99/100        1       1       1       1       1        99/100  99/100      \r
+100    100     1       1       1       1               1       1       1       1       1       1               1             \r
+101    100     1.01    1       1  1/99 1   1/100       1       1       1       1       1       1  1/100        1  1/100      \r
+102    100     1.02    1       1  1/50 1   1/50        1       1       1       1       1       1  2/100        1  1/50       \r
+103    100     1.03    1       1  1/33 1   3/100       1       1       1       1       1       1  3/100        1  3/100      \r
+104    100     1.04    1       1  1/25 1   1/25        1       1       1       1  1/16 1       1  4/100        1  1/25       \r
+105    100     1.05    1       1  1/20 1   1/20        1       1       1       1  1/16 1 1/10  1  5/100        1  1/20       \r
+106    100     1.06    1       1  3/50 1   3/50        1       1       1       1  1/16 1 1/10  1  6/100        1  3/50       \r
+107    100     1.07    1       1  4/57 1   7/100       1       1       1 1/8   1  1/16 1 1/10  1  7/100        1  7/100      \r
+108    100     1.08    1       1  2/25 1   2/25        1       1       1 1/8   1  1/16 1 1/10  1  8/100        1  2/25       \r
+109    100     1.09    1       1  1/11 1   9/100       1       1       1 1/8   1  1/16 1 1/10  1  9/100        1  9/100      \r
+110    100     1.1     1 1/9   1  1/10 1   1/10        1       1       1 1/8   1  2/16 1 1/10  1 10/100        1  1/10       \r
+111    100     1.11    1 1/9   1  1/9  1  11/100       1       1       1 1/8   1  2/16 1 1/10  1 11/100        1 11/100      \r
+112    100     1.12    1 1/8   1  3/25 1   3/25        1       1       1 1/8   1  2/16 1 1/10  1 12/100        1  3/25       \r
+113    100     1.13    1 1/8   1 10/77 1  13/100       1       1 1/4   1 1/8   1  2/16 1 1/10  1 13/100        1 13/100      \r
+114    100     1.14    1 1/7   1  7/50 1   7/50        1       1 1/4   1 1/8   1  2/16 1 1/10  1 14/100        1  7/50       \r
+115    100     1.15    1 1/7   1  3/20 1   3/20        1       1 1/4   1 1/8   1  2/16 1 1/10  1 15/100        1  3/20       \r
+116    100     1.16    1 1/6   1  4/25 1   4/25        1       1 1/4   1 1/8   1  3/16 1 2/10  1 16/100        1  4/25       \r
+117    100     1.17    1 1/6   1  9/53 1  17/100       1       1 1/4   1 1/8   1  3/16 1 2/10  1 17/100        1 17/100      \r
+118    100     1.18    1 1/6   1  9/50 1   9/50        1       1 1/4   1 1/8   1  3/16 1 2/10  1 18/100        1  9/50       \r
+119    100     1.19    1 1/5   1 15/79 1  19/100       1       1 1/4   1 2/8   1  3/16 1 2/10  1 19/100        1 19/100      \r
+120    100     1.2     1 1/5   1  1/5  1   1/5         1       1 1/4   1 2/8   1  3/16 1 2/10  1 20/100        1  1/5        \r
+121    100     1.21    1 1/5   1 17/81 1  21/100       1       1 1/4   1 2/8   1  3/16 1 2/10  1 21/100        1 21/100      \r
+122    100     1.22    1 2/9   1 11/50 1  11/50        1       1 1/4   1 2/8   1  4/16 1 2/10  1 22/100        1 11/50       \r
+123    100     1.23    1 2/9   1 20/87 1  23/100       1       1 1/4   1 2/8   1  4/16 1 2/10  1 23/100        1 23/100      \r
+124    100     1.24    1 1/4   1  6/25 1   6/25        1       1 1/4   1 2/8   1  4/16 1 2/10  1 24/100        1  6/25       \r
+125    100     1.25    1 1/4   1  1/4  1   1/4         1 1/2   1 1/4   1 2/8   1  4/16 1 3/10  1 25/100        1  1/4        \r
+126    100     1.26    1 1/4   1 13/50 1  13/50        1 1/2   1 1/4   1 2/8   1  4/16 1 3/10  1 26/100        1 13/50       \r
+127    100     1.27    1 1/4   1 10/37 1  27/100       1 1/2   1 1/4   1 2/8   1  4/16 1 3/10  1 27/100        1 27/100      \r
+-103   201     -0.512437811    - 1/2   - 41/80 - 103/201       - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 51/100        - 103/201      \r
+-100   201     -0.497512438    - 1/2   -  1/2  - 100/201       - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 50/100        - 100/201      \r
+-97    201     -0.482587065    - 1/2   - 14/29 -  97/201       - 1/2   - 2/4   - 4/8   -  8/16 - 5/10  - 48/100        - 97/201      \r
+-94    201     -0.467661692    - 1/2   - 29/62 -  94/201       - 1/2   - 2/4   - 4/8   -  7/16 - 5/10  - 47/100        - 94/201      \r
+-91    201     -0.452736318    - 4/9   - 24/53 -  91/201       - 1/2   - 2/4   - 4/8   -  7/16 - 5/10  - 45/100        - 91/201      \r
+-88    201     -0.437810945    - 4/9   -  7/16 -  88/201       - 1/2   - 2/4   - 4/8   -  7/16 - 4/10  - 44/100        - 88/201      \r
+-85    201     -0.422885572    - 3/7   - 11/26 -  85/201       - 1/2   - 2/4   - 3/8   -  7/16 - 4/10  - 42/100        - 85/201      \r
+-82    201     -0.407960199    - 2/5   - 31/76 -  82/201       - 1/2   - 2/4   - 3/8   -  7/16 - 4/10  - 41/100        - 82/201      \r
+-79    201     -0.393034826    - 2/5   - 11/28 -  79/201       - 1/2   - 2/4   - 3/8   -  6/16 - 4/10  - 39/100        - 79/201      \r
+-76    201     -0.378109453    - 3/8   - 31/82 -  76/201       - 1/2   - 2/4   - 3/8   -  6/16 - 4/10  - 38/100        - 76/201      \r
+-73    201     -0.36318408     - 1/3   -  4/11 -  73/201       - 1/2   - 1/4   - 3/8   -  6/16 - 4/10  - 36/100        - 73/201      \r
+-70    201     -0.348258706    - 1/3   - 31/89 -  70/201       - 1/2   - 1/4   - 3/8   -  6/16 - 3/10  - 35/100        - 70/201      \r
+-67    201     -0.333333333    - 1/3   -  1/3  -   1/3         - 1/2   - 1/4   - 3/8   -  5/16 - 3/10  - 33/100        -  1/3        \r
+-64    201     -0.31840796     - 1/3   -  7/22 -  64/201       - 1/2   - 1/4   - 3/8   -  5/16 - 3/10  - 32/100        - 64/201      \r
+-61    201     -0.303482587    - 1/3   - 17/56 -  61/201       - 1/2   - 1/4   - 2/8   -  5/16 - 3/10  - 30/100        - 61/201      \r
+-58    201     -0.288557214    - 2/7   - 15/52 -  58/201       - 1/2   - 1/4   - 2/8   -  5/16 - 3/10  - 29/100        - 58/201      \r
+-55    201     -0.273631841    - 2/7   - 26/95 -  55/201       - 1/2   - 1/4   - 2/8   -  4/16 - 3/10  - 27/100        - 55/201      \r
+-52    201     -0.258706468    - 1/4   - 15/58 -  52/201       - 1/2   - 1/4   - 2/8   -  4/16 - 3/10  - 26/100        - 52/201      \r
+-49    201     -0.243781095    - 1/4   - 10/41 -  49/201       -0      - 1/4   - 2/8   -  4/16 - 2/10  - 24/100        - 49/201      \r
+-46    201     -0.228855721    - 2/9   - 19/83 -  46/201       -0      - 1/4   - 2/8   -  4/16 - 2/10  - 23/100        - 46/201      \r
+-43    201     -0.213930348    - 1/5   -  3/14 -  43/201       -0      - 1/4   - 2/8   -  3/16 - 2/10  - 21/100        - 43/201      \r
+-40    201     -0.199004975    - 1/5   -  1/5  -  40/201       -0      - 1/4   - 2/8   -  3/16 - 2/10  - 20/100        - 40/201      \r
+-37    201     -0.184079602    - 1/5   -  7/38 -  37/201       -0      - 1/4   - 1/8   -  3/16 - 2/10  - 18/100        - 37/201      \r
+-34    201     -0.169154229    - 1/6   - 11/65 -  34/201       -0      - 1/4   - 1/8   -  3/16 - 2/10  - 17/100        - 34/201      \r
+-31    201     -0.154228856    - 1/6   -  2/13 -  31/201       -0      - 1/4   - 1/8   -  2/16 - 2/10  - 15/100        - 31/201      \r
+-28    201     -0.139303483    - 1/7   - 11/79 -  28/201       -0      - 1/4   - 1/8   -  2/16 - 1/10  - 14/100        - 28/201      \r
+-25    201     -0.124378109    - 1/8   -  1/8  -  25/201       -0      -0      - 1/8   -  2/16 - 1/10  - 12/100        - 25/201      \r
+-22    201     -0.109452736    - 1/9   -  7/64 -  22/201       -0      -0      - 1/8   -  2/16 - 1/10  - 11/100        - 22/201      \r
+-19    201     -0.094527363    -0      -  7/74 -  19/201       -0      -0      - 1/8   -  2/16 - 1/10  -  9/100        - 19/201      \r
+-16    201     -0.07960199     -0      -  7/88 -  16/201       -0      -0      - 1/8   -  1/16 - 1/10  -  8/100        - 16/201      \r
+-13    201     -0.064676617    -0      -  2/31 -  13/201       -0      -0      - 1/8   -  1/16 - 1/10  -  6/100        - 13/201      \r
+-10    201     -0.049751244    -0      -  1/20 -  10/201       -0      -0      -0      -  1/16 -0      -  5/100        - 10/201      \r
+-7     201     -0.034825871    -0      -  3/86 -   7/201       -0      -0      -0      -  1/16 -0      -  3/100        -  7/201      \r
+-4     201     -0.019900498    -0      -  1/50 -   4/201       -0      -0      -0      -0              -0      -  2/100        -  4/201      \r
+-1     201     -0.004975124    -0      -0              -   1/201       -0      -0      -0      -0              -0      -0              -  1/201      \r
+2      201     0.009950249     0       0          2/201        0       0       0       0       0         1/100   2/201      \r
+5      201     0.024875622     0         1/40     5/201        0       0       0       0       0         2/100   5/201      \r
+8      201     0.039800995     0         1/25     8/201        0       0       0         1/16  0         4/100   8/201      \r
+11     201     0.054726368     0         4/73    11/201        0       0       0         1/16   1/10     5/100  11/201      \r
+14     201     0.069651741     0         3/43    14/201        0       0        1/8      1/16   1/10     7/100  14/201      \r
+17     201     0.084577114     0         6/71    17/201        0       0        1/8      1/16   1/10     8/100  17/201      \r
+20     201     0.099502488     0         1/10    20/201        0       0        1/8      2/16   1/10    10/100  20/201      \r
+23     201     0.114427861      1/9      4/35    23/201        0       0        1/8      2/16   1/10    11/100  23/201      \r
+26     201     0.129353234      1/8     11/85    26/201        0        1/4     1/8      2/16   1/10    13/100  26/201      \r
+29     201     0.144278607      1/7     14/97    29/201        0        1/4     1/8      2/16   1/10    14/100  29/201      \r
+32     201     0.15920398       1/6      7/44    32/201        0        1/4     1/8      3/16   2/10    16/100  32/201      \r
+35     201     0.174129353      1/6      4/23    35/201        0        1/4     1/8      3/16   2/10    17/100  35/201      \r
+38     201     0.189054726      1/5      7/37    38/201        0        1/4     2/8      3/16   2/10    19/100  38/201      \r
+41     201     0.2039801        1/5     10/49    41/201        0        1/4     2/8      3/16   2/10    20/100  41/201      \r
+44     201     0.218905473      2/9      7/32    44/201        0        1/4     2/8      4/16   2/10    22/100  44/201      \r
+47     201     0.233830846      1/4     18/77    47/201        0        1/4     2/8      4/16   2/10    23/100  47/201      \r
+50     201     0.248756219      1/4      1/4     50/201        0        1/4     2/8      4/16   2/10    25/100  50/201      \r
+53     201     0.263681592      1/4     24/91    53/201         1/2     1/4     2/8      4/16   3/10    26/100  53/201      \r
+56     201     0.278606965      2/7     17/61    56/201         1/2     1/4     2/8      4/16   3/10    28/100  56/201      \r
+59     201     0.293532338      2/7     27/92    59/201         1/2     1/4     2/8      5/16   3/10    29/100  59/201      \r
+62     201     0.308457711      1/3     29/94    62/201         1/2     1/4     2/8      5/16   3/10    31/100  62/201      \r
+65     201     0.323383085      1/3     11/34    65/201         1/2     1/4     3/8      5/16   3/10    32/100  65/201      \r
+68     201     0.338308458      1/3     23/68    68/201         1/2     1/4     3/8      5/16   3/10    34/100  68/201      \r
+71     201     0.353233831      1/3      6/17    71/201         1/2     1/4     3/8      6/16   4/10    35/100  71/201      \r
+74     201     0.368159204      3/8      7/19    74/201         1/2     1/4     3/8      6/16   4/10    37/100  74/201      \r
+77     201     0.383084577      3/8     18/47    77/201         1/2     2/4     3/8      6/16   4/10    38/100  77/201      \r
+80     201     0.39800995       2/5     39/98    80/201         1/2     2/4     3/8      6/16   4/10    40/100  80/201      \r
+83     201     0.412935323      2/5     19/46    83/201         1/2     2/4     3/8      7/16   4/10    41/100  83/201      \r
+86     201     0.427860697      3/7      3/7     86/201         1/2     2/4     3/8      7/16   4/10    43/100  86/201      \r
+89     201     0.44278607       4/9     31/70    89/201         1/2     2/4     4/8      7/16   4/10    44/100  89/201      \r
+92     201     0.457711443      1/2     27/59    92/201         1/2     2/4     4/8      7/16   5/10    46/100  92/201      \r
+95     201     0.472636816      1/2     26/55    95/201         1/2     2/4     4/8      8/16   5/10    47/100  95/201      \r
+98     201     0.487562189      1/2     39/80    98/201         1/2     2/4     4/8      8/16   5/10    49/100  98/201      \r
+101    201     0.502487562      1/2      1/2    101/201         1/2     2/4     4/8      8/16   5/10    50/100  101/201      \r
+104    201     0.517412935      1/2     15/29   104/201         1/2     2/4     4/8      8/16   5/10    52/100  104/201      \r
+107    201     0.532338308      1/2     33/62   107/201         1/2     2/4     4/8      9/16   5/10    53/100  107/201      \r
+110    201     0.547263682      5/9     29/53   110/201         1/2     2/4     4/8      9/16   5/10    55/100  110/201      \r
+113    201     0.562189055      5/9      9/16   113/201         1/2     2/4     4/8      9/16   6/10    56/100  113/201      \r
+116    201     0.577114428      4/7     15/26   116/201         1/2     2/4     5/8      9/16   6/10    58/100  116/201      \r
+119    201     0.592039801      3/5     45/76   119/201         1/2     2/4     5/8      9/16   6/10    59/100  119/201      \r
+122    201     0.606965174      3/5     17/28   122/201         1/2     2/4     5/8     10/16   6/10    61/100  122/201      \r
+125    201     0.621890547      5/8     51/82   125/201         1/2     2/4     5/8     10/16   6/10    62/100  125/201      \r
+128    201     0.63681592       2/3      7/11   128/201         1/2     3/4     5/8     10/16   6/10    64/100  128/201      \r
+131    201     0.651741294      2/3     58/89   131/201         1/2     3/4     5/8     10/16   7/10    65/100  131/201      \r
+134    201     0.666666667      2/3      2/3      2/3           1/2     3/4     5/8     11/16   7/10    67/100   2/3        \r
+137    201     0.68159204       2/3     15/22   137/201         1/2     3/4     5/8     11/16   7/10    68/100  137/201      \r
+140    201     0.696517413      2/3     39/56   140/201         1/2     3/4     6/8     11/16   7/10    70/100  140/201      \r
+143    201     0.711442786      5/7     37/52   143/201         1/2     3/4     6/8     11/16   7/10    71/100  143/201      \r
+146    201     0.726368159      5/7     69/95   146/201         1/2     3/4     6/8     12/16   7/10    73/100  146/201      \r
+149    201     0.741293532      3/4     43/58   149/201         1/2     3/4     6/8     12/16   7/10    74/100  149/201      \r
+152    201     0.756218905      3/4     31/41   152/201        1        3/4     6/8     12/16   8/10    76/100  152/201      \r
+155    201     0.771144279      7/9     64/83   155/201        1        3/4     6/8     12/16   8/10    77/100  155/201      \r
+158    201     0.786069652      4/5     11/14   158/201        1        3/4     6/8     13/16   8/10    79/100  158/201      \r
+161    201     0.800995025      4/5      4/5    161/201        1        3/4     6/8     13/16   8/10    80/100  161/201      \r
+164    201     0.815920398      4/5     31/38   164/201        1        3/4     7/8     13/16   8/10    82/100  164/201      \r
+167    201     0.830845771      5/6     54/65   167/201        1        3/4     7/8     13/16   8/10    83/100  167/201      \r
+170    201     0.845771144      5/6     11/13   170/201        1        3/4     7/8     14/16   8/10    85/100  170/201      \r
+173    201     0.860696517      6/7     68/79   173/201        1        3/4     7/8     14/16   9/10    86/100  173/201      \r
+176    201     0.875621891      7/8      7/8    176/201        1       1        7/8     14/16   9/10    88/100  176/201      \r
+179    201     0.890547264      8/9     57/64   179/201        1       1        7/8     14/16   9/10    89/100  179/201      \r
+182    201     0.905472637     1        67/74   182/201        1       1        7/8     14/16   9/10    91/100  182/201      \r
+185    201     0.92039801      1        81/88   185/201        1       1        7/8     15/16   9/10    92/100  185/201      \r
+188    201     0.935323383     1        29/31   188/201        1       1        7/8     15/16   9/10    94/100  188/201      \r
+191    201     0.950248756     1        19/20   191/201        1       1       1        15/16  1        95/100  191/201      \r
+194    201     0.965174129     1        83/86   194/201        1       1       1        15/16  1        97/100  194/201      \r
+197    201     0.980099502     1        49/50   197/201        1       1       1       1       1        98/100  197/201      \r
+200    201     0.995024876     1       1        200/201        1       1       1       1       1       1                200/201      \r
+203    201     1.009950249     1       1       1   2/201       1       1       1       1       1       1  1/100        1  2/201      \r
+206    201     1.024875622     1       1  1/40 1   5/201       1       1       1       1       1       1  2/100        1  5/201      \r
+209    201     1.039800995     1       1  1/25 1   8/201       1       1       1       1  1/16 1       1  4/100        1  8/201      \r
+212    201     1.054726368     1       1  4/73 1  11/201       1       1       1       1  1/16 1 1/10  1  5/100        1 11/201      \r
+215    201     1.069651741     1       1  3/43 1  14/201       1       1       1 1/8   1  1/16 1 1/10  1  7/100        1 14/201      \r
+218    201     1.084577114     1       1  6/71 1  17/201       1       1       1 1/8   1  1/16 1 1/10  1  8/100        1 17/201      \r
+221    201     1.099502488     1       1  1/10 1  20/201       1       1       1 1/8   1  2/16 1 1/10  1 10/100        1 20/201      \r
+224    201     1.114427861     1 1/9   1  4/35 1  23/201       1       1       1 1/8   1  2/16 1 1/10  1 11/100        1 23/201      \r
+227    201     1.129353234     1 1/8   1 11/85 1  26/201       1       1 1/4   1 1/8   1  2/16 1 1/10  1 13/100        1 26/201      \r
+230    201     1.144278607     1 1/7   1 14/97 1  29/201       1       1 1/4   1 1/8   1  2/16 1 1/10  1 14/100        1 29/201      \r
+233    201     1.15920398      1 1/6   1  7/44 1  32/201       1       1 1/4   1 1/8   1  3/16 1 2/10  1 16/100        1 32/201      \r
+236    201     1.174129353     1 1/6   1  4/23 1  35/201       1       1 1/4   1 1/8   1  3/16 1 2/10  1 17/100        1 35/201      \r
+239    201     1.189054726     1 1/5   1  7/37 1  38/201       1       1 1/4   1 2/8   1  3/16 1 2/10  1 19/100        1 38/201      \r
+242    201     1.2039801       1 1/5   1 10/49 1  41/201       1       1 1/4   1 2/8   1  3/16 1 2/10  1 20/100        1 41/201      \r
+245    201     1.218905473     1 2/9   1  7/32 1  44/201       1       1 1/4   1 2/8   1  4/16 1 2/10  1 22/100        1 44/201      \r
+248    201     1.233830846     1 1/4   1 18/77 1  47/201       1       1 1/4   1 2/8   1  4/16 1 2/10  1 23/100        1 47/201      \r
+251    201     1.248756219     1 1/4   1  1/4  1  50/201       1       1 1/4   1 2/8   1  4/16 1 2/10  1 25/100        1 50/201      \r
+254    201     1.263681592     1 1/4   1 24/91 1  53/201       1 1/2   1 1/4   1 2/8   1  4/16 1 3/10  1 26/100        1 53/201      \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
+                                                                                               \r
diff --git a/test-data/spreadsheet/54686_fraction_formats.xls b/test-data/spreadsheet/54686_fraction_formats.xls
new file mode 100644 (file)
index 0000000..d802995
Binary files /dev/null and b/test-data/spreadsheet/54686_fraction_formats.xls differ