diff --git a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java index 930f8b420..46740cc38 100644 --- a/src/java/org/apache/poi/ss/usermodel/DataFormatter.java +++ b/src/java/org/apache/poi/ss/usermodel/DataFormatter.java @@ -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; *
  • simulate Excel's handling of a format string of all # when the value is 0. * Excel will output "", DataFormatter will output "0". * - * @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 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 index 000000000..1522e7afb --- /dev/null +++ b/src/java/org/apache/poi/ss/usermodel/FractionFormat.java @@ -0,0 +1,271 @@ +/* + * 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.text.FieldPosition; +import java.text.Format; +import java.text.ParsePosition; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.poi.ss.formula.eval.NotImplementedException; + +/** + *

    Format class that handles Excel style fractions, such as "# #/#" and "#/###"

    + * + *

    As of this writing, this is still not 100% accurate, but it does a reasonable job + * of trying to mimic Excel's fraction calculations. It does not currently + * maintain Excel's spacing.

    + * + *

    This class relies on a method lifted nearly verbatim from org.apache.math.fraction. + * If further uses for Commons Math are found, we will consider adding it as a dependency. + * For now, we have in-lined the one method to keep things simple.

    + */ +/* One question remains...is the value of epsilon in calcFractionMaxDenom reasonable? */ +@SuppressWarnings("serial") +public class FractionFormat extends Format { + private final static Pattern DENOM_FORMAT_PATTERN = Pattern.compile("(?:(#+)|(\\d+))"); + + //this was chosen to match the earlier limitation of max denom power + //it can be expanded to get closer to Excel's calculations + //with custom formats # #/######### + //but as of this writing, the numerators and denominators + //with formats of that nature on very small values were quite + //far from Excel's calculations + private final static int MAX_DENOM_POW = 4; + + //there are two options: + //a) an exact denominator is specified in the formatString + //b) the maximum denominator can be calculated from the formatString + private final int exactDenom; + private final int maxDenom; + + private final String wholePartFormatString; + /** + * Single parameter ctor + * @param denomFormatString The format string for the denominator + */ + public FractionFormat(String wholePartFormatString, String denomFormatString) { + this.wholePartFormatString = wholePartFormatString; + //init exactDenom and maxDenom + Matcher m = DENOM_FORMAT_PATTERN.matcher(denomFormatString); + int tmpExact = -1; + int tmpMax = -1; + if (m.find()){ + if (m.group(2) != null){ + try{ + tmpExact = Integer.parseInt(m.group(2)); + //if the denom is 0, fall back to the default: tmpExact=100 + + if (tmpExact == 0){ + tmpExact = -1; + } + } catch (NumberFormatException e){ + //should never happen + } + } else if (m.group(1) != null) { + int len = m.group(1).length(); + len = len > MAX_DENOM_POW ? MAX_DENOM_POW : len; + tmpMax = (int)Math.pow(10, len); + } else { + tmpExact = 100; + } + } + if (tmpExact <= 0 && tmpMax <= 0){ + //use 100 as the default denom if something went horribly wrong + tmpExact = 100; + } + exactDenom = tmpExact; + maxDenom = tmpMax; + } + + public String format(Number num) { + + double doubleValue = num.doubleValue(); + + boolean isNeg = (doubleValue < 0.0f) ? true : false; + double absDoubleValue = Math.abs(doubleValue); + + double wholePart = Math.floor(absDoubleValue); + double decPart = absDoubleValue - wholePart; + if (wholePart + decPart == 0) { + return "0"; + } + + //if the absolute value is smaller than 1 over the exact or maxDenom + //you can stop here and return "0" + if (absDoubleValue < (1/Math.max(exactDenom, maxDenom))){ + return "0"; + } + + //this is necessary to prevent overflow in the maxDenom calculation + //stink1 + if (wholePart+(int)decPart == wholePart+decPart){ + + StringBuilder sb = new StringBuilder(); + if (isNeg){ + sb.append("-"); + } + sb.append(Integer.toString((int)wholePart)); + return sb.toString(); + } + + SimpleFraction fract = null; + try{ + //this should be the case because of the constructor + if (exactDenom > 0){ + fract = calcFractionExactDenom(decPart, exactDenom); + } else { + fract = calcFractionMaxDenom(decPart, maxDenom); + } + } catch (SimpleFractionException e){ + e.printStackTrace(); + return Double.toString(doubleValue); + } + + StringBuilder sb = new StringBuilder(); + + //now format the results + if (isNeg){ + sb.append("-"); + } + + //if whole part has to go into the numerator + if ("".equals(wholePartFormatString)){ + int trueNum = (fract.getDenominator()*(int)wholePart)+fract.getNumerator(); + sb.append(trueNum).append("/").append(fract.getDenominator()); + return sb.toString(); + } + + + //short circuit if fraction is 0 or 1 + if (fract.getNumerator() == 0){ + sb.append(Integer.toString((int)wholePart)); + return sb.toString(); + } else if (fract.getNumerator() == fract.getDenominator()){ + sb.append(Integer.toString((int)wholePart+1)); + return sb.toString(); + } + //as mentioned above, this ignores the exact space formatting in Excel + if (wholePart > 0){ + sb.append(Integer.toString((int)wholePart)).append(" "); + } + sb.append(fract.getNumerator()).append("/").append(fract.getDenominator()); + return sb.toString(); + } + + 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"); + } + + private SimpleFraction calcFractionMaxDenom(double value, int maxDenominator) + throws SimpleFractionException{ + /* + * Lifted wholesale from org.apache.math.fraction.Fraction 2.2 + */ + double epsilon = 0.000000000001f; + int maxIterations = 100; + long overflow = Integer.MAX_VALUE; + double r0 = value; + long a0 = (long)Math.floor(r0); + if (Math.abs(a0) > overflow) { + throw new SimpleFractionException( + String.format("value > Integer.MAX_VALUE: %d.", a0)); + } + + // check for (almost) integer arguments, which should not go + // to iterations. + if (Math.abs(a0 - value) < epsilon) { + return new SimpleFraction((int) a0, 1); + } + + long p0 = 1; + long q0 = 0; + long p1 = a0; + long q1 = 1; + + long p2 = 0; + long q2 = 1; + + int n = 0; + boolean stop = false; + do { + ++n; + double r1 = 1.0 / (r0 - a0); + long a1 = (long)Math.floor(r1); + p2 = (a1 * p1) + p0; + q2 = (a1 * q1) + q0; + if ((Math.abs(p2) > overflow) || (Math.abs(q2) > overflow)) { + throw new SimpleFractionException( + String.format("Greater than overflow in loop %f, %d, %d", value, p2, q2)); + } + + double convergent = (double)p2 / (double)q2; + if (n < maxIterations && Math.abs(convergent - value) > epsilon && q2 < maxDenominator) { + p0 = p1; + p1 = p2; + q0 = q1; + q1 = q2; + a0 = a1; + r0 = r1; + } else { + stop = true; + } + } while (!stop); + + if (n >= maxIterations) { + throw new SimpleFractionException("n greater than max iterations " + value + " : " + maxIterations); + } + + if (q2 < maxDenominator) { + return new SimpleFraction((int) p2, (int) q2); + } else { + return new SimpleFraction((int) p1, (int) q1); + } + } + + private SimpleFraction calcFractionExactDenom(double val, int exactDenom){ + int num = (int)Math.round(val*(double)exactDenom); + return new SimpleFraction(num,exactDenom); + } + + private class SimpleFraction { + private final int num; + private final int denom; + + public SimpleFraction(int num, int denom) { + this.num = num; + this.denom = denom; + } + + public int getNumerator() { + return num; + } + public int getDenominator() { + return denom; + } + } + private class SimpleFractionException extends Throwable{ + private SimpleFractionException(String message){ + super(message); + } + } +} diff --git a/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java b/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java index c6233fcf3..6dcd6ebeb 100644 --- a/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java +++ b/src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java @@ -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 index 000000000..1db2507ea --- /dev/null +++ b/src/testcases/org/apache/poi/ss/usermodel/TestFractionFormat.java @@ -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 index 000000000..0de773efb --- /dev/null +++ b/test-data/spreadsheet/54686_fraction_formats.txt @@ -0,0 +1,374 @@ +Numerator Denominator Double 1Digit 2Digit 3Digit Half Quarter Eight Sixteenth Tenth 100th Tika-1132 +4051 8750153 0.000462963 0 0 0 0 0 0 0 0 0 4051/8750153 +-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 +-104 100 -1.04 -1 -1 1/25 -1 1/25 -1 -1 -1 -1 1/16 -1 -1 4/100 -1 1/25 +-103 100 -1.03 -1 -1 1/33 -1 3/100 -1 -1 -1 -1 -1 -1 3/100 -1 3/100 +-102 100 -1.02 -1 -1 1/50 -1 1/50 -1 -1 -1 -1 -1 -1 2/100 -1 1/50 +-101 100 -1.01 -1 -1 1/99 -1 1/100 -1 -1 -1 -1 -1 -1 1/100 -1 1/100 +-100 100 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +-99 100 -0.99 -1 - 98/99 - 99/100 -1 -1 -1 -1 -1 - 99/100 - 99/100 +-98 100 -0.98 -1 - 49/50 - 49/50 -1 -1 -1 -1 -1 - 98/100 - 49/50 +-97 100 -0.97 -1 - 32/33 - 97/100 -1 -1 -1 -1 -1 - 97/100 - 97/100 +-96 100 -0.96 -1 - 24/25 - 24/25 -1 -1 -1 - 15/16 -1 - 96/100 - 24/25 +-95 100 -0.95 -1 - 19/20 - 19/20 -1 -1 -1 - 15/16 -1 - 95/100 - 19/20 +-94 100 -0.94 -1 - 47/50 - 47/50 -1 -1 -1 - 15/16 - 9/10 - 94/100 - 47/50 +-93 100 -0.93 -1 - 40/43 - 93/100 -1 -1 - 7/8 - 15/16 - 9/10 - 93/100 - 93/100 +-92 100 -0.92 -1 - 23/25 - 23/25 -1 -1 - 7/8 - 15/16 - 9/10 - 92/100 - 23/25 +-91 100 -0.91 -1 - 81/89 - 91/100 -1 -1 - 7/8 - 15/16 - 9/10 - 91/100 - 91/100 +-90 100 -0.9 - 8/9 - 9/10 - 9/10 -1 -1 - 7/8 - 14/16 - 9/10 - 90/100 - 9/10 +-89 100 -0.89 - 8/9 - 8/9 - 89/100 -1 -1 - 7/8 - 14/16 - 9/10 - 89/100 - 89/100 +-88 100 -0.88 - 7/8 - 22/25 - 22/25 -1 -1 - 7/8 - 14/16 - 9/10 - 88/100 - 22/25 +-87 100 -0.87 - 7/8 - 67/77 - 87/100 -1 - 3/4 - 7/8 - 14/16 - 9/10 - 87/100 - 87/100 +-86 100 -0.86 - 6/7 - 43/50 - 43/50 -1 - 3/4 - 7/8 - 14/16 - 9/10 - 86/100 - 43/50 +-85 100 -0.85 - 6/7 - 17/20 - 17/20 -1 - 3/4 - 7/8 - 14/16 - 9/10 - 85/100 - 17/20 +-84 100 -0.84 - 5/6 - 21/25 - 21/25 -1 - 3/4 - 7/8 - 13/16 - 8/10 - 84/100 - 21/25 +-83 100 -0.83 - 5/6 - 39/47 - 83/100 -1 - 3/4 - 7/8 - 13/16 - 8/10 - 83/100 - 83/100 +-82 100 -0.82 - 5/6 - 41/50 - 41/50 -1 - 3/4 - 7/8 - 13/16 - 8/10 - 82/100 - 41/50 +-81 100 -0.81 - 4/5 - 64/79 - 81/100 -1 - 3/4 - 6/8 - 13/16 - 8/10 - 81/100 - 81/100 +-80 100 -0.8 - 4/5 - 4/5 - 4/5 -1 - 3/4 - 6/8 - 13/16 - 8/10 - 80/100 - 4/5 +-79 100 -0.79 - 4/5 - 64/81 - 79/100 -1 - 3/4 - 6/8 - 13/16 - 8/10 - 79/100 - 79/100 +-78 100 -0.78 - 7/9 - 39/50 - 39/50 -1 - 3/4 - 6/8 - 12/16 - 8/10 - 78/100 - 39/50 +-77 100 -0.77 - 7/9 - 67/87 - 77/100 -1 - 3/4 - 6/8 - 12/16 - 8/10 - 77/100 - 77/100 +-76 100 -0.76 - 3/4 - 19/25 - 19/25 -1 - 3/4 - 6/8 - 12/16 - 8/10 - 76/100 - 19/25 +-75 100 -0.75 - 3/4 - 3/4 - 3/4 -1 - 3/4 - 6/8 - 12/16 - 8/10 - 75/100 - 3/4 +-74 100 -0.74 - 3/4 - 37/50 - 37/50 - 1/2 - 3/4 - 6/8 - 12/16 - 7/10 - 74/100 - 37/50 +-73 100 -0.73 - 3/4 - 46/63 - 73/100 - 1/2 - 3/4 - 6/8 - 12/16 - 7/10 - 73/100 - 73/100 +-72 100 -0.72 - 5/7 - 18/25 - 18/25 - 1/2 - 3/4 - 6/8 - 12/16 - 7/10 - 72/100 - 18/25 +-71 100 -0.71 - 5/7 - 22/31 - 71/100 - 1/2 - 3/4 - 6/8 - 11/16 - 7/10 - 71/100 - 71/100 +-70 100 -0.7 - 2/3 - 7/10 - 7/10 - 1/2 - 3/4 - 6/8 - 11/16 - 7/10 - 70/100 - 7/10 +-69 100 -0.69 - 2/3 - 20/29 - 69/100 - 1/2 - 3/4 - 6/8 - 11/16 - 7/10 - 69/100 - 69/100 +-68 100 -0.68 - 2/3 - 17/25 - 17/25 - 1/2 - 3/4 - 5/8 - 11/16 - 7/10 - 68/100 - 17/25 +-67 100 -0.67 - 2/3 - 65/97 - 67/100 - 1/2 - 3/4 - 5/8 - 11/16 - 7/10 - 67/100 - 67/100 +-66 100 -0.66 - 2/3 - 33/50 - 33/50 - 1/2 - 3/4 - 5/8 - 11/16 - 7/10 - 66/100 - 33/50 +-65 100 -0.65 - 2/3 - 13/20 - 13/20 - 1/2 - 3/4 - 5/8 - 10/16 - 7/10 - 65/100 - 13/20 +-64 100 -0.64 - 2/3 - 16/25 - 16/25 - 1/2 - 3/4 - 5/8 - 10/16 - 6/10 - 64/100 - 16/25 +-63 100 -0.63 - 5/8 - 46/73 - 63/100 - 1/2 - 3/4 - 5/8 - 10/16 - 6/10 - 63/100 - 63/100 +-62 100 -0.62 - 5/8 - 31/50 - 31/50 - 1/2 - 2/4 - 5/8 - 10/16 - 6/10 - 62/100 - 31/50 +-61 100 -0.61 - 3/5 - 36/59 - 61/100 - 1/2 - 2/4 - 5/8 - 10/16 - 6/10 - 61/100 - 61/100 +-60 100 -0.6 - 3/5 - 3/5 - 3/5 - 1/2 - 2/4 - 5/8 - 10/16 - 6/10 - 60/100 - 3/5 +-59 100 -0.59 - 3/5 - 23/39 - 59/100 - 1/2 - 2/4 - 5/8 - 9/16 - 6/10 - 59/100 - 59/100 +-58 100 -0.58 - 4/7 - 29/50 - 29/50 - 1/2 - 2/4 - 5/8 - 9/16 - 6/10 - 58/100 - 29/50 +-57 100 -0.57 - 4/7 - 53/93 - 57/100 - 1/2 - 2/4 - 5/8 - 9/16 - 6/10 - 57/100 - 57/100 +-56 100 -0.56 - 5/9 - 14/25 - 14/25 - 1/2 - 2/4 - 4/8 - 9/16 - 6/10 - 56/100 - 14/25 +-55 100 -0.55 - 5/9 - 11/20 - 11/20 - 1/2 - 2/4 - 4/8 - 9/16 - 6/10 - 55/100 - 11/20 +-54 100 -0.54 - 1/2 - 27/50 - 27/50 - 1/2 - 2/4 - 4/8 - 9/16 - 5/10 - 54/100 - 27/50 +-53 100 -0.53 - 1/2 - 44/83 - 53/100 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 53/100 - 53/100 +-52 100 -0.52 - 1/2 - 13/25 - 13/25 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 52/100 - 13/25 +-51 100 -0.51 - 1/2 - 25/49 - 51/100 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 51/100 - 51/100 +-50 100 -0.5 - 1/2 - 1/2 - 1/2 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 50/100 - 1/2 +-49 100 -0.49 - 1/2 - 24/49 - 49/100 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 49/100 - 49/100 +-48 100 -0.48 - 1/2 - 12/25 - 12/25 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 48/100 - 12/25 +-47 100 -0.47 - 1/2 - 8/17 - 47/100 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 47/100 - 47/100 +-46 100 -0.46 - 1/2 - 23/50 - 23/50 - 1/2 - 2/4 - 4/8 - 7/16 - 5/10 - 46/100 - 23/50 +-45 100 -0.45 - 4/9 - 9/20 - 9/20 - 1/2 - 2/4 - 4/8 - 7/16 - 5/10 - 45/100 - 9/20 +-44 100 -0.44 - 4/9 - 11/25 - 11/25 - 1/2 - 2/4 - 4/8 - 7/16 - 4/10 - 44/100 - 11/25 +-43 100 -0.43 - 3/7 - 3/7 - 43/100 - 1/2 - 2/4 - 3/8 - 7/16 - 4/10 - 43/100 - 43/100 +-42 100 -0.42 - 3/7 - 21/50 - 21/50 - 1/2 - 2/4 - 3/8 - 7/16 - 4/10 - 42/100 - 21/50 +-41 100 -0.41 - 2/5 - 16/39 - 41/100 - 1/2 - 2/4 - 3/8 - 7/16 - 4/10 - 41/100 - 41/100 +-40 100 -0.4 - 2/5 - 2/5 - 2/5 - 1/2 - 2/4 - 3/8 - 6/16 - 4/10 - 40/100 - 2/5 +-39 100 -0.39 - 2/5 - 16/41 - 39/100 - 1/2 - 2/4 - 3/8 - 6/16 - 4/10 - 39/100 - 39/100 +-38 100 -0.38 - 3/8 - 19/50 - 19/50 - 1/2 - 2/4 - 3/8 - 6/16 - 4/10 - 38/100 - 19/50 +-37 100 -0.37 - 3/8 - 10/27 - 37/100 - 1/2 - 1/4 - 3/8 - 6/16 - 4/10 - 37/100 - 37/100 +-36 100 -0.36 - 1/3 - 9/25 - 9/25 - 1/2 - 1/4 - 3/8 - 6/16 - 4/10 - 36/100 - 9/25 +-35 100 -0.35 - 1/3 - 7/20 - 7/20 - 1/2 - 1/4 - 3/8 - 6/16 - 4/10 - 35/100 - 7/20 +-34 100 -0.34 - 1/3 - 17/50 - 17/50 - 1/2 - 1/4 - 3/8 - 5/16 - 3/10 - 34/100 - 17/50 +-33 100 -0.33 - 1/3 - 1/3 - 33/100 - 1/2 - 1/4 - 3/8 - 5/16 - 3/10 - 33/100 - 33/100 +-32 100 -0.32 - 1/3 - 8/25 - 8/25 - 1/2 - 1/4 - 3/8 - 5/16 - 3/10 - 32/100 - 8/25 +-31 100 -0.31 - 1/3 - 22/71 - 31/100 - 1/2 - 1/4 - 2/8 - 5/16 - 3/10 - 31/100 - 31/100 +-30 100 -0.3 - 2/7 - 3/10 - 3/10 - 1/2 - 1/4 - 2/8 - 5/16 - 3/10 - 30/100 - 3/10 +-29 100 -0.29 - 2/7 - 20/69 - 29/100 - 1/2 - 1/4 - 2/8 - 5/16 - 3/10 - 29/100 - 29/100 +-28 100 -0.28 - 2/7 - 7/25 - 7/25 - 1/2 - 1/4 - 2/8 - 4/16 - 3/10 - 28/100 - 7/25 +-27 100 -0.27 - 1/4 - 10/37 - 27/100 - 1/2 - 1/4 - 2/8 - 4/16 - 3/10 - 27/100 - 27/100 +-26 100 -0.26 - 1/4 - 13/50 - 13/50 - 1/2 - 1/4 - 2/8 - 4/16 - 3/10 - 26/100 - 13/50 +-25 100 -0.25 - 1/4 - 1/4 - 1/4 - 1/2 - 1/4 - 2/8 - 4/16 - 3/10 - 25/100 - 1/4 +-24 100 -0.24 - 1/4 - 6/25 - 6/25 -0 - 1/4 - 2/8 - 4/16 - 2/10 - 24/100 - 6/25 +-23 100 -0.23 - 2/9 - 3/13 - 23/100 -0 - 1/4 - 2/8 - 4/16 - 2/10 - 23/100 - 23/100 +-22 100 -0.22 - 2/9 - 11/50 - 11/50 -0 - 1/4 - 2/8 - 4/16 - 2/10 - 22/100 - 11/50 +-21 100 -0.21 - 1/5 - 17/81 - 21/100 -0 - 1/4 - 2/8 - 3/16 - 2/10 - 21/100 - 21/100 +-20 100 -0.2 - 1/5 - 1/5 - 1/5 -0 - 1/4 - 2/8 - 3/16 - 2/10 - 20/100 - 1/5 +-19 100 -0.19 - 1/5 - 15/79 - 19/100 -0 - 1/4 - 2/8 - 3/16 - 2/10 - 19/100 - 19/100 +-18 100 -0.18 - 1/6 - 9/50 - 9/50 -0 - 1/4 - 1/8 - 3/16 - 2/10 - 18/100 - 9/50 +-17 100 -0.17 - 1/6 - 8/47 - 17/100 -0 - 1/4 - 1/8 - 3/16 - 2/10 - 17/100 - 17/100 +-16 100 -0.16 - 1/6 - 4/25 - 4/25 -0 - 1/4 - 1/8 - 3/16 - 2/10 - 16/100 - 4/25 +-15 100 -0.15 - 1/7 - 3/20 - 3/20 -0 - 1/4 - 1/8 - 2/16 - 2/10 - 15/100 - 3/20 +-14 100 -0.14 - 1/7 - 7/50 - 7/50 -0 - 1/4 - 1/8 - 2/16 - 1/10 - 14/100 - 7/50 +-13 100 -0.13 - 1/8 - 3/23 - 13/100 -0 - 1/4 - 1/8 - 2/16 - 1/10 - 13/100 - 13/100 +-12 100 -0.12 - 1/8 - 3/25 - 3/25 -0 -0 - 1/8 - 2/16 - 1/10 - 12/100 - 3/25 +-11 100 -0.11 - 1/9 - 10/91 - 11/100 -0 -0 - 1/8 - 2/16 - 1/10 - 11/100 - 11/100 +-10 100 -0.1 -0 - 1/10 - 1/10 -0 -0 - 1/8 - 2/16 - 1/10 - 10/100 - 1/10 +-9 100 -0.09 -0 - 1/11 - 9/100 -0 -0 - 1/8 - 1/16 - 1/10 - 9/100 - 9/100 +-8 100 -0.08 -0 - 2/25 - 2/25 -0 -0 - 1/8 - 1/16 - 1/10 - 8/100 - 2/25 +-7 100 -0.07 -0 - 4/57 - 7/100 -0 -0 - 1/8 - 1/16 - 1/10 - 7/100 - 7/100 +-6 100 -0.06 -0 - 3/50 - 3/50 -0 -0 -0 - 1/16 - 1/10 - 6/100 - 3/50 +-5 100 -0.05 -0 - 1/20 - 1/20 -0 -0 -0 - 1/16 - 1/10 - 5/100 - 1/20 +-4 100 -0.04 -0 - 1/25 - 1/25 -0 -0 -0 - 1/16 -0 - 4/100 - 1/25 +-3 100 -0.03 -0 - 2/67 - 3/100 -0 -0 -0 -0 -0 - 3/100 - 3/100 +-2 100 -0.02 -0 - 1/50 - 1/50 -0 -0 -0 -0 -0 - 2/100 - 1/50 +-1 100 -0.01 -0 -0 - 1/100 -0 -0 -0 -0 -0 - 1/100 - 1/100 +0 100 0 0 0 0 0 0 0 0 0 0 0 +1 100 0.01 0 0 1/100 0 0 0 0 0 1/100 1/100 +2 100 0.02 0 1/50 1/50 0 0 0 0 0 2/100 1/50 +3 100 0.03 0 2/67 3/100 0 0 0 0 0 3/100 3/100 +4 100 0.04 0 1/25 1/25 0 0 0 1/16 0 4/100 1/25 +5 100 0.05 0 1/20 1/20 0 0 0 1/16 1/10 5/100 1/20 +6 100 0.06 0 3/50 3/50 0 0 0 1/16 1/10 6/100 3/50 +7 100 0.07 0 4/57 7/100 0 0 1/8 1/16 1/10 7/100 7/100 +8 100 0.08 0 2/25 2/25 0 0 1/8 1/16 1/10 8/100 2/25 +9 100 0.09 0 1/11 9/100 0 0 1/8 1/16 1/10 9/100 9/100 +10 100 0.1 0 1/10 1/10 0 0 1/8 2/16 1/10 10/100 1/10 +11 100 0.11 1/9 10/91 11/100 0 0 1/8 2/16 1/10 11/100 11/100 +12 100 0.12 1/8 3/25 3/25 0 0 1/8 2/16 1/10 12/100 3/25 +13 100 0.13 1/8 3/23 13/100 0 1/4 1/8 2/16 1/10 13/100 13/100 +14 100 0.14 1/7 7/50 7/50 0 1/4 1/8 2/16 1/10 14/100 7/50 +15 100 0.15 1/7 3/20 3/20 0 1/4 1/8 2/16 2/10 15/100 3/20 +16 100 0.16 1/6 4/25 4/25 0 1/4 1/8 3/16 2/10 16/100 4/25 +17 100 0.17 1/6 8/47 17/100 0 1/4 1/8 3/16 2/10 17/100 17/100 +18 100 0.18 1/6 9/50 9/50 0 1/4 1/8 3/16 2/10 18/100 9/50 +19 100 0.19 1/5 15/79 19/100 0 1/4 2/8 3/16 2/10 19/100 19/100 +20 100 0.2 1/5 1/5 1/5 0 1/4 2/8 3/16 2/10 20/100 1/5 +21 100 0.21 1/5 17/81 21/100 0 1/4 2/8 3/16 2/10 21/100 21/100 +22 100 0.22 2/9 11/50 11/50 0 1/4 2/8 4/16 2/10 22/100 11/50 +23 100 0.23 2/9 3/13 23/100 0 1/4 2/8 4/16 2/10 23/100 23/100 +24 100 0.24 1/4 6/25 6/25 0 1/4 2/8 4/16 2/10 24/100 6/25 +25 100 0.25 1/4 1/4 1/4 1/2 1/4 2/8 4/16 3/10 25/100 1/4 +26 100 0.26 1/4 13/50 13/50 1/2 1/4 2/8 4/16 3/10 26/100 13/50 +27 100 0.27 1/4 10/37 27/100 1/2 1/4 2/8 4/16 3/10 27/100 27/100 +28 100 0.28 2/7 7/25 7/25 1/2 1/4 2/8 4/16 3/10 28/100 7/25 +29 100 0.29 2/7 20/69 29/100 1/2 1/4 2/8 5/16 3/10 29/100 29/100 +30 100 0.3 2/7 3/10 3/10 1/2 1/4 2/8 5/16 3/10 30/100 3/10 +31 100 0.31 1/3 22/71 31/100 1/2 1/4 2/8 5/16 3/10 31/100 31/100 +32 100 0.32 1/3 8/25 8/25 1/2 1/4 3/8 5/16 3/10 32/100 8/25 +33 100 0.33 1/3 1/3 33/100 1/2 1/4 3/8 5/16 3/10 33/100 33/100 +34 100 0.34 1/3 17/50 17/50 1/2 1/4 3/8 5/16 3/10 34/100 17/50 +35 100 0.35 1/3 7/20 7/20 1/2 1/4 3/8 6/16 4/10 35/100 7/20 +36 100 0.36 1/3 9/25 9/25 1/2 1/4 3/8 6/16 4/10 36/100 9/25 +37 100 0.37 3/8 10/27 37/100 1/2 1/4 3/8 6/16 4/10 37/100 37/100 +38 100 0.38 3/8 19/50 19/50 1/2 2/4 3/8 6/16 4/10 38/100 19/50 +39 100 0.39 2/5 16/41 39/100 1/2 2/4 3/8 6/16 4/10 39/100 39/100 +40 100 0.4 2/5 2/5 2/5 1/2 2/4 3/8 6/16 4/10 40/100 2/5 +41 100 0.41 2/5 16/39 41/100 1/2 2/4 3/8 7/16 4/10 41/100 41/100 +42 100 0.42 3/7 21/50 21/50 1/2 2/4 3/8 7/16 4/10 42/100 21/50 +43 100 0.43 3/7 3/7 43/100 1/2 2/4 3/8 7/16 4/10 43/100 43/100 +44 100 0.44 4/9 11/25 11/25 1/2 2/4 4/8 7/16 4/10 44/100 11/25 +45 100 0.45 4/9 9/20 9/20 1/2 2/4 4/8 7/16 5/10 45/100 9/20 +46 100 0.46 1/2 23/50 23/50 1/2 2/4 4/8 7/16 5/10 46/100 23/50 +47 100 0.47 1/2 8/17 47/100 1/2 2/4 4/8 8/16 5/10 47/100 47/100 +48 100 0.48 1/2 12/25 12/25 1/2 2/4 4/8 8/16 5/10 48/100 12/25 +49 100 0.49 1/2 24/49 49/100 1/2 2/4 4/8 8/16 5/10 49/100 49/100 +50 100 0.5 1/2 1/2 1/2 1/2 2/4 4/8 8/16 5/10 50/100 1/2 +51 100 0.51 1/2 25/49 51/100 1/2 2/4 4/8 8/16 5/10 51/100 51/100 +52 100 0.52 1/2 13/25 13/25 1/2 2/4 4/8 8/16 5/10 52/100 13/25 +53 100 0.53 1/2 44/83 53/100 1/2 2/4 4/8 8/16 5/10 53/100 53/100 +54 100 0.54 1/2 27/50 27/50 1/2 2/4 4/8 9/16 5/10 54/100 27/50 +55 100 0.55 5/9 11/20 11/20 1/2 2/4 4/8 9/16 6/10 55/100 11/20 +56 100 0.56 5/9 14/25 14/25 1/2 2/4 4/8 9/16 6/10 56/100 14/25 +57 100 0.57 4/7 53/93 57/100 1/2 2/4 5/8 9/16 6/10 57/100 57/100 +58 100 0.58 4/7 29/50 29/50 1/2 2/4 5/8 9/16 6/10 58/100 29/50 +59 100 0.59 3/5 23/39 59/100 1/2 2/4 5/8 9/16 6/10 59/100 59/100 +60 100 0.6 3/5 3/5 3/5 1/2 2/4 5/8 10/16 6/10 60/100 3/5 +61 100 0.61 3/5 36/59 61/100 1/2 2/4 5/8 10/16 6/10 61/100 61/100 +62 100 0.62 5/8 31/50 31/50 1/2 2/4 5/8 10/16 6/10 62/100 31/50 +63 100 0.63 5/8 46/73 63/100 1/2 3/4 5/8 10/16 6/10 63/100 63/100 +64 100 0.64 2/3 16/25 16/25 1/2 3/4 5/8 10/16 6/10 64/100 16/25 +65 100 0.65 2/3 13/20 13/20 1/2 3/4 5/8 10/16 7/10 65/100 13/20 +66 100 0.66 2/3 33/50 33/50 1/2 3/4 5/8 11/16 7/10 66/100 33/50 +67 100 0.67 2/3 65/97 67/100 1/2 3/4 5/8 11/16 7/10 67/100 67/100 +68 100 0.68 2/3 17/25 17/25 1/2 3/4 5/8 11/16 7/10 68/100 17/25 +69 100 0.69 2/3 20/29 69/100 1/2 3/4 6/8 11/16 7/10 69/100 69/100 +70 100 0.7 2/3 7/10 7/10 1/2 3/4 6/8 11/16 7/10 70/100 7/10 +71 100 0.71 5/7 22/31 71/100 1/2 3/4 6/8 11/16 7/10 71/100 71/100 +72 100 0.72 5/7 18/25 18/25 1/2 3/4 6/8 12/16 7/10 72/100 18/25 +73 100 0.73 3/4 46/63 73/100 1/2 3/4 6/8 12/16 7/10 73/100 73/100 +74 100 0.74 3/4 37/50 37/50 1/2 3/4 6/8 12/16 7/10 74/100 37/50 +75 100 0.75 3/4 3/4 3/4 1 3/4 6/8 12/16 8/10 75/100 3/4 +76 100 0.76 3/4 19/25 19/25 1 3/4 6/8 12/16 8/10 76/100 19/25 +77 100 0.77 7/9 67/87 77/100 1 3/4 6/8 12/16 8/10 77/100 77/100 +78 100 0.78 7/9 39/50 39/50 1 3/4 6/8 12/16 8/10 78/100 39/50 +79 100 0.79 4/5 64/81 79/100 1 3/4 6/8 13/16 8/10 79/100 79/100 +80 100 0.8 4/5 4/5 4/5 1 3/4 6/8 13/16 8/10 80/100 4/5 +81 100 0.81 4/5 64/79 81/100 1 3/4 6/8 13/16 8/10 81/100 81/100 +82 100 0.82 5/6 41/50 41/50 1 3/4 7/8 13/16 8/10 82/100 41/50 +83 100 0.83 5/6 39/47 83/100 1 3/4 7/8 13/16 8/10 83/100 83/100 +84 100 0.84 5/6 21/25 21/25 1 3/4 7/8 13/16 8/10 84/100 21/25 +85 100 0.85 6/7 17/20 17/20 1 3/4 7/8 14/16 9/10 85/100 17/20 +86 100 0.86 6/7 43/50 43/50 1 3/4 7/8 14/16 9/10 86/100 43/50 +87 100 0.87 7/8 67/77 87/100 1 3/4 7/8 14/16 9/10 87/100 87/100 +88 100 0.88 7/8 22/25 22/25 1 1 7/8 14/16 9/10 88/100 22/25 +89 100 0.89 8/9 8/9 89/100 1 1 7/8 14/16 9/10 89/100 89/100 +90 100 0.9 8/9 9/10 9/10 1 1 7/8 14/16 9/10 90/100 9/10 +91 100 0.91 1 81/89 91/100 1 1 7/8 15/16 9/10 91/100 91/100 +92 100 0.92 1 23/25 23/25 1 1 7/8 15/16 9/10 92/100 23/25 +93 100 0.93 1 40/43 93/100 1 1 7/8 15/16 9/10 93/100 93/100 +94 100 0.94 1 47/50 47/50 1 1 1 15/16 9/10 94/100 47/50 +95 100 0.95 1 19/20 19/20 1 1 1 15/16 1 95/100 19/20 +96 100 0.96 1 24/25 24/25 1 1 1 15/16 1 96/100 24/25 +97 100 0.97 1 32/33 97/100 1 1 1 1 1 97/100 97/100 +98 100 0.98 1 49/50 49/50 1 1 1 1 1 98/100 49/50 +99 100 0.99 1 98/99 99/100 1 1 1 1 1 99/100 99/100 +100 100 1 1 1 1 1 1 1 1 1 1 1 +101 100 1.01 1 1 1/99 1 1/100 1 1 1 1 1 1 1/100 1 1/100 +102 100 1.02 1 1 1/50 1 1/50 1 1 1 1 1 1 2/100 1 1/50 +103 100 1.03 1 1 1/33 1 3/100 1 1 1 1 1 1 3/100 1 3/100 +104 100 1.04 1 1 1/25 1 1/25 1 1 1 1 1/16 1 1 4/100 1 1/25 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +-103 201 -0.512437811 - 1/2 - 41/80 - 103/201 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 51/100 - 103/201 +-100 201 -0.497512438 - 1/2 - 1/2 - 100/201 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 50/100 - 100/201 +-97 201 -0.482587065 - 1/2 - 14/29 - 97/201 - 1/2 - 2/4 - 4/8 - 8/16 - 5/10 - 48/100 - 97/201 +-94 201 -0.467661692 - 1/2 - 29/62 - 94/201 - 1/2 - 2/4 - 4/8 - 7/16 - 5/10 - 47/100 - 94/201 +-91 201 -0.452736318 - 4/9 - 24/53 - 91/201 - 1/2 - 2/4 - 4/8 - 7/16 - 5/10 - 45/100 - 91/201 +-88 201 -0.437810945 - 4/9 - 7/16 - 88/201 - 1/2 - 2/4 - 4/8 - 7/16 - 4/10 - 44/100 - 88/201 +-85 201 -0.422885572 - 3/7 - 11/26 - 85/201 - 1/2 - 2/4 - 3/8 - 7/16 - 4/10 - 42/100 - 85/201 +-82 201 -0.407960199 - 2/5 - 31/76 - 82/201 - 1/2 - 2/4 - 3/8 - 7/16 - 4/10 - 41/100 - 82/201 +-79 201 -0.393034826 - 2/5 - 11/28 - 79/201 - 1/2 - 2/4 - 3/8 - 6/16 - 4/10 - 39/100 - 79/201 +-76 201 -0.378109453 - 3/8 - 31/82 - 76/201 - 1/2 - 2/4 - 3/8 - 6/16 - 4/10 - 38/100 - 76/201 +-73 201 -0.36318408 - 1/3 - 4/11 - 73/201 - 1/2 - 1/4 - 3/8 - 6/16 - 4/10 - 36/100 - 73/201 +-70 201 -0.348258706 - 1/3 - 31/89 - 70/201 - 1/2 - 1/4 - 3/8 - 6/16 - 3/10 - 35/100 - 70/201 +-67 201 -0.333333333 - 1/3 - 1/3 - 1/3 - 1/2 - 1/4 - 3/8 - 5/16 - 3/10 - 33/100 - 1/3 +-64 201 -0.31840796 - 1/3 - 7/22 - 64/201 - 1/2 - 1/4 - 3/8 - 5/16 - 3/10 - 32/100 - 64/201 +-61 201 -0.303482587 - 1/3 - 17/56 - 61/201 - 1/2 - 1/4 - 2/8 - 5/16 - 3/10 - 30/100 - 61/201 +-58 201 -0.288557214 - 2/7 - 15/52 - 58/201 - 1/2 - 1/4 - 2/8 - 5/16 - 3/10 - 29/100 - 58/201 +-55 201 -0.273631841 - 2/7 - 26/95 - 55/201 - 1/2 - 1/4 - 2/8 - 4/16 - 3/10 - 27/100 - 55/201 +-52 201 -0.258706468 - 1/4 - 15/58 - 52/201 - 1/2 - 1/4 - 2/8 - 4/16 - 3/10 - 26/100 - 52/201 +-49 201 -0.243781095 - 1/4 - 10/41 - 49/201 -0 - 1/4 - 2/8 - 4/16 - 2/10 - 24/100 - 49/201 +-46 201 -0.228855721 - 2/9 - 19/83 - 46/201 -0 - 1/4 - 2/8 - 4/16 - 2/10 - 23/100 - 46/201 +-43 201 -0.213930348 - 1/5 - 3/14 - 43/201 -0 - 1/4 - 2/8 - 3/16 - 2/10 - 21/100 - 43/201 +-40 201 -0.199004975 - 1/5 - 1/5 - 40/201 -0 - 1/4 - 2/8 - 3/16 - 2/10 - 20/100 - 40/201 +-37 201 -0.184079602 - 1/5 - 7/38 - 37/201 -0 - 1/4 - 1/8 - 3/16 - 2/10 - 18/100 - 37/201 +-34 201 -0.169154229 - 1/6 - 11/65 - 34/201 -0 - 1/4 - 1/8 - 3/16 - 2/10 - 17/100 - 34/201 +-31 201 -0.154228856 - 1/6 - 2/13 - 31/201 -0 - 1/4 - 1/8 - 2/16 - 2/10 - 15/100 - 31/201 +-28 201 -0.139303483 - 1/7 - 11/79 - 28/201 -0 - 1/4 - 1/8 - 2/16 - 1/10 - 14/100 - 28/201 +-25 201 -0.124378109 - 1/8 - 1/8 - 25/201 -0 -0 - 1/8 - 2/16 - 1/10 - 12/100 - 25/201 +-22 201 -0.109452736 - 1/9 - 7/64 - 22/201 -0 -0 - 1/8 - 2/16 - 1/10 - 11/100 - 22/201 +-19 201 -0.094527363 -0 - 7/74 - 19/201 -0 -0 - 1/8 - 2/16 - 1/10 - 9/100 - 19/201 +-16 201 -0.07960199 -0 - 7/88 - 16/201 -0 -0 - 1/8 - 1/16 - 1/10 - 8/100 - 16/201 +-13 201 -0.064676617 -0 - 2/31 - 13/201 -0 -0 - 1/8 - 1/16 - 1/10 - 6/100 - 13/201 +-10 201 -0.049751244 -0 - 1/20 - 10/201 -0 -0 -0 - 1/16 -0 - 5/100 - 10/201 +-7 201 -0.034825871 -0 - 3/86 - 7/201 -0 -0 -0 - 1/16 -0 - 3/100 - 7/201 +-4 201 -0.019900498 -0 - 1/50 - 4/201 -0 -0 -0 -0 -0 - 2/100 - 4/201 +-1 201 -0.004975124 -0 -0 - 1/201 -0 -0 -0 -0 -0 -0 - 1/201 +2 201 0.009950249 0 0 2/201 0 0 0 0 0 1/100 2/201 +5 201 0.024875622 0 1/40 5/201 0 0 0 0 0 2/100 5/201 +8 201 0.039800995 0 1/25 8/201 0 0 0 1/16 0 4/100 8/201 +11 201 0.054726368 0 4/73 11/201 0 0 0 1/16 1/10 5/100 11/201 +14 201 0.069651741 0 3/43 14/201 0 0 1/8 1/16 1/10 7/100 14/201 +17 201 0.084577114 0 6/71 17/201 0 0 1/8 1/16 1/10 8/100 17/201 +20 201 0.099502488 0 1/10 20/201 0 0 1/8 2/16 1/10 10/100 20/201 +23 201 0.114427861 1/9 4/35 23/201 0 0 1/8 2/16 1/10 11/100 23/201 +26 201 0.129353234 1/8 11/85 26/201 0 1/4 1/8 2/16 1/10 13/100 26/201 +29 201 0.144278607 1/7 14/97 29/201 0 1/4 1/8 2/16 1/10 14/100 29/201 +32 201 0.15920398 1/6 7/44 32/201 0 1/4 1/8 3/16 2/10 16/100 32/201 +35 201 0.174129353 1/6 4/23 35/201 0 1/4 1/8 3/16 2/10 17/100 35/201 +38 201 0.189054726 1/5 7/37 38/201 0 1/4 2/8 3/16 2/10 19/100 38/201 +41 201 0.2039801 1/5 10/49 41/201 0 1/4 2/8 3/16 2/10 20/100 41/201 +44 201 0.218905473 2/9 7/32 44/201 0 1/4 2/8 4/16 2/10 22/100 44/201 +47 201 0.233830846 1/4 18/77 47/201 0 1/4 2/8 4/16 2/10 23/100 47/201 +50 201 0.248756219 1/4 1/4 50/201 0 1/4 2/8 4/16 2/10 25/100 50/201 +53 201 0.263681592 1/4 24/91 53/201 1/2 1/4 2/8 4/16 3/10 26/100 53/201 +56 201 0.278606965 2/7 17/61 56/201 1/2 1/4 2/8 4/16 3/10 28/100 56/201 +59 201 0.293532338 2/7 27/92 59/201 1/2 1/4 2/8 5/16 3/10 29/100 59/201 +62 201 0.308457711 1/3 29/94 62/201 1/2 1/4 2/8 5/16 3/10 31/100 62/201 +65 201 0.323383085 1/3 11/34 65/201 1/2 1/4 3/8 5/16 3/10 32/100 65/201 +68 201 0.338308458 1/3 23/68 68/201 1/2 1/4 3/8 5/16 3/10 34/100 68/201 +71 201 0.353233831 1/3 6/17 71/201 1/2 1/4 3/8 6/16 4/10 35/100 71/201 +74 201 0.368159204 3/8 7/19 74/201 1/2 1/4 3/8 6/16 4/10 37/100 74/201 +77 201 0.383084577 3/8 18/47 77/201 1/2 2/4 3/8 6/16 4/10 38/100 77/201 +80 201 0.39800995 2/5 39/98 80/201 1/2 2/4 3/8 6/16 4/10 40/100 80/201 +83 201 0.412935323 2/5 19/46 83/201 1/2 2/4 3/8 7/16 4/10 41/100 83/201 +86 201 0.427860697 3/7 3/7 86/201 1/2 2/4 3/8 7/16 4/10 43/100 86/201 +89 201 0.44278607 4/9 31/70 89/201 1/2 2/4 4/8 7/16 4/10 44/100 89/201 +92 201 0.457711443 1/2 27/59 92/201 1/2 2/4 4/8 7/16 5/10 46/100 92/201 +95 201 0.472636816 1/2 26/55 95/201 1/2 2/4 4/8 8/16 5/10 47/100 95/201 +98 201 0.487562189 1/2 39/80 98/201 1/2 2/4 4/8 8/16 5/10 49/100 98/201 +101 201 0.502487562 1/2 1/2 101/201 1/2 2/4 4/8 8/16 5/10 50/100 101/201 +104 201 0.517412935 1/2 15/29 104/201 1/2 2/4 4/8 8/16 5/10 52/100 104/201 +107 201 0.532338308 1/2 33/62 107/201 1/2 2/4 4/8 9/16 5/10 53/100 107/201 +110 201 0.547263682 5/9 29/53 110/201 1/2 2/4 4/8 9/16 5/10 55/100 110/201 +113 201 0.562189055 5/9 9/16 113/201 1/2 2/4 4/8 9/16 6/10 56/100 113/201 +116 201 0.577114428 4/7 15/26 116/201 1/2 2/4 5/8 9/16 6/10 58/100 116/201 +119 201 0.592039801 3/5 45/76 119/201 1/2 2/4 5/8 9/16 6/10 59/100 119/201 +122 201 0.606965174 3/5 17/28 122/201 1/2 2/4 5/8 10/16 6/10 61/100 122/201 +125 201 0.621890547 5/8 51/82 125/201 1/2 2/4 5/8 10/16 6/10 62/100 125/201 +128 201 0.63681592 2/3 7/11 128/201 1/2 3/4 5/8 10/16 6/10 64/100 128/201 +131 201 0.651741294 2/3 58/89 131/201 1/2 3/4 5/8 10/16 7/10 65/100 131/201 +134 201 0.666666667 2/3 2/3 2/3 1/2 3/4 5/8 11/16 7/10 67/100 2/3 +137 201 0.68159204 2/3 15/22 137/201 1/2 3/4 5/8 11/16 7/10 68/100 137/201 +140 201 0.696517413 2/3 39/56 140/201 1/2 3/4 6/8 11/16 7/10 70/100 140/201 +143 201 0.711442786 5/7 37/52 143/201 1/2 3/4 6/8 11/16 7/10 71/100 143/201 +146 201 0.726368159 5/7 69/95 146/201 1/2 3/4 6/8 12/16 7/10 73/100 146/201 +149 201 0.741293532 3/4 43/58 149/201 1/2 3/4 6/8 12/16 7/10 74/100 149/201 +152 201 0.756218905 3/4 31/41 152/201 1 3/4 6/8 12/16 8/10 76/100 152/201 +155 201 0.771144279 7/9 64/83 155/201 1 3/4 6/8 12/16 8/10 77/100 155/201 +158 201 0.786069652 4/5 11/14 158/201 1 3/4 6/8 13/16 8/10 79/100 158/201 +161 201 0.800995025 4/5 4/5 161/201 1 3/4 6/8 13/16 8/10 80/100 161/201 +164 201 0.815920398 4/5 31/38 164/201 1 3/4 7/8 13/16 8/10 82/100 164/201 +167 201 0.830845771 5/6 54/65 167/201 1 3/4 7/8 13/16 8/10 83/100 167/201 +170 201 0.845771144 5/6 11/13 170/201 1 3/4 7/8 14/16 8/10 85/100 170/201 +173 201 0.860696517 6/7 68/79 173/201 1 3/4 7/8 14/16 9/10 86/100 173/201 +176 201 0.875621891 7/8 7/8 176/201 1 1 7/8 14/16 9/10 88/100 176/201 +179 201 0.890547264 8/9 57/64 179/201 1 1 7/8 14/16 9/10 89/100 179/201 +182 201 0.905472637 1 67/74 182/201 1 1 7/8 14/16 9/10 91/100 182/201 +185 201 0.92039801 1 81/88 185/201 1 1 7/8 15/16 9/10 92/100 185/201 +188 201 0.935323383 1 29/31 188/201 1 1 7/8 15/16 9/10 94/100 188/201 +191 201 0.950248756 1 19/20 191/201 1 1 1 15/16 1 95/100 191/201 +194 201 0.965174129 1 83/86 194/201 1 1 1 15/16 1 97/100 194/201 +197 201 0.980099502 1 49/50 197/201 1 1 1 1 1 98/100 197/201 +200 201 0.995024876 1 1 200/201 1 1 1 1 1 1 200/201 +203 201 1.009950249 1 1 1 2/201 1 1 1 1 1 1 1/100 1 2/201 +206 201 1.024875622 1 1 1/40 1 5/201 1 1 1 1 1 1 2/100 1 5/201 +209 201 1.039800995 1 1 1/25 1 8/201 1 1 1 1 1/16 1 1 4/100 1 8/201 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +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 + + + + + + + + + + + + + + + + + + + diff --git a/test-data/spreadsheet/54686_fraction_formats.xls b/test-data/spreadsheet/54686_fraction_formats.xls new file mode 100644 index 000000000..d802995b1 Binary files /dev/null and b/test-data/spreadsheet/54686_fraction_formats.xls differ