Create compact/human-friendly floats using unicode vulgar fractions

时间:2015-09-01 22:53:46

标签: python unicode floating-point

Are there any modules (preferably in the standard library), that can turn a float number into something the is more human friendly? Maybe it's not more human friendly, but at least more compact.

eg. 4.625 would become "4⅝"

(Bonus brownie points for recognizing pi to a reasonable precision)

This code outline was the best I could come up with:

import unicodedata

def simplify_float(number):
    vf = "VULGAR FRACTION "
    vulgars = {0.125 : unicodedata.lookup(vf + "ONE EIGHTH"),
               0.2   : unicodedata.lookup(vf + "ONE FIFTH"),
               0.25  : unicodedata.lookup(vf + "ONE QUARTER"),
               0.375 : unicodedata.lookup(vf + "THREE EIGHTHS"),
               0.4   : unicodedata.lookup(vf + "TWO FIFTHS"),
               0.5   : unicodedata.lookup(vf + "ONE HALF"),
               0.6   : unicodedata.lookup(vf + "THREE FIFTHS"),
               0.625 : unicodedata.lookup(vf + "FIVE EIGHTHS"),
               0.75  : unicodedata.lookup(vf + "THREE QUARTERS"),
               0.8   : unicodedata.lookup(vf + "FOUR FIFTHS"),
               0.875 : unicodedata.lookup(vf + "SEVEN EIGHTHS")}

    decimal = int(number)
    if number == decimal:
        return unicode(decimal)

    vulgar = vulgars.get(number - decimal)
    if vulgar:
        if decimal == 0:
            return vulgar
        return "%d%s" % (decimal, vulgar)
    return "%.1f" % number

Going the other direction is pretty easy using the unicodedata module, but I couldn't find a good way to author these strings in the first place.

1 个答案:

答案 0 :(得分:3)

only twenty of these fraction forms in Unicode。不太可能会有更多(因为它们仅存在与其他字符集的向后兼容性),所以对它们进行硬编码可能足够强大。

编码分数的一般方法是使用 U + 2044 FRACTION SLASH。字体整形/布局引擎允许使用分数斜线(例如1/2)渲染数字,作为倾斜或堆叠分数(例如,½) - 但是,我没有遇到任何这样做(甚至普通渲染是不幸的是很难看。)

import math
import fractions

VULGAR_FRACTIONS = {(5, 8) : '\u215D', ...}

def compact_float(number):
    parts = math.modf(number)
    fraction = fractions.Fraction(parts[0])
    simple = (fraction.numerator, fraction.denominator)
    form = VULGAR_FRACTIONS.get(simple)
    return '%i%s' % (parts[1], form) if form else str(number)

目前尚不清楚处理精度的最佳方法是什么(例如1/3),因为它取决于您的数字存在的格式以及可接受的错误数量。