/* * Copyright (c) 2011 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include int maxDiv = 64; int conv_metric = 0; static void printusage(void) { extern char *__progname; printf("Usage: %s [-mi] [-M maxdiv] [number]\n", __progname); exit(1); } static void print_nearest_fractional(double val) { int ths = 2, thsNearest = 999, iNearest = 999, i; double errNearest = HUGE_VAL; double nearest = HUGE_VAL; double d; if (fabs(val - 1.0) < 0.00005) { printf("1\n"); } for (ths = 2; ths <= maxDiv; ths *= 2) { for (i = 1; i < ths; i++) { d = (double)i/(double)ths; if (fabs(val - d) < errNearest) { errNearest = fabs(val - d); nearest = d; iNearest = i; thsNearest = ths; } } } if (errNearest < 0.00005) { printf("%d/%d (%.04f)\n", iNearest, thsNearest, nearest); } else if (nearest > val) { printf("%d/%d (%.04f) -%.04f\n", iNearest, thsNearest, nearest, errNearest); } else { printf("%d/%d (%.04f) +%.04f\n", iNearest, thsNearest, nearest, errNearest); } } int main(int argc, char *argv[]) { char *ep, *s, c, ch; int pt, i; while ((ch = getopt(argc, argv, "M:m?h")) != -1) { switch (ch) { case 'M': maxDiv = atoi(optarg); break; case 'm': conv_metric = 1; break; default: printusage(); } } argv += optind; argc -= optind; if (argc == 0) printusage(); for (i = 0; i < argc; i++) { double val; char *arg = argv[i]; if ((s = strchr(arg, '/')) != NULL) { int num = atoi(arg); int den = atoi(s+1); if (s == '\0' || den == 0) { errx(1, "-i: invalid fraction"); } val = (double)num/den; } else { val = strtod(arg, &ep); if (arg[0] == '\0' || *ep != '\0') { errx(1, "-i: invalid value"); } } if (conv_metric) { val /= 25.4; } print_nearest_fractional(val); } return (0); }