import math from eos.utils.round import roundToPrec, roundDec def formatAmount(val, prec=3, lowest=0, highest=0, currency=False, forceSign=False, unitName=None): """ Add suffix to value, transform value to match new suffix and round it. Keyword arguments: val -- value to process prec -- precision of final number (number of significant positions to show) lowest -- lowest order for suffixizing for numbers 0 < |num| < 1 highest -- highest order for suffixizing for numbers |num| > 1 currency -- if currency, billion suffix will be B instead of G forceSign -- if True, positive numbers are signed too unitName -- if specified, will be formatted into a string """ if val is None: return "" if val == math.inf: return "\u221e" if unitName is None else "\u221e {}".format(unitName) # Define suffix maps posSuffixMap = {3: "k", 6: "M", 9: "B" if currency is True else "G"} negSuffixMap = {-6: '\u03bc', -3: "m"} # Define tuple of the map keys # As we're going to go from the biggest order of abs(key), sort # them differently due to one set of values being negative # and other positive posOrders = tuple(sorted(iter(posSuffixMap.keys()), reverse=True)) negOrders = tuple(sorted(iter(negSuffixMap.keys()), reverse=False)) # Find the least abs(key) posLowest = min(posOrders) negHighest = max(negOrders) # By default, mantissa takes just value and no suffix mantissa, suffix = val, "" # Positive suffixes if abs(val) > 1 and highest >= posLowest: # Start from highest possible suffix for key in posOrders: # Find first suitable suffix and check if it's not above highest order if abs(val) >= 10 ** key and key <= highest: mantissa, suffix = val / float(10 ** key), posSuffixMap[key] # Do additional step to eliminate results like 999999 => 1000k # If we're already using our greatest order, we can't do anything useful if posOrders.index(key) == 0: break else: # Get order greater than current prevKey = posOrders[posOrders.index(key) - 1] # Check if the key to which we potentially can change is greater # than our highest boundary if prevKey > highest: # If it is, bail - we already have acceptable results break # Find multiplier to get from one order to another orderDiff = 10 ** (prevKey - key) # If rounded mantissa according to our specifications is greater than # or equal to multiplier if roundToPrec(mantissa, prec) >= orderDiff: # Divide mantissa and use suffix of greater order mantissa, suffix = mantissa / orderDiff, posSuffixMap[prevKey] # Otherwise consider current results as acceptable break # Take numbers between 0 and 1, and matching/below highest possible negative suffix elif abs(val) < 1 and val != 0 and lowest <= negHighest: # Start from lowest possible suffix for key in negOrders: # Get next order try: nextKey = negOrders[negOrders.index(key) + 1] except IndexError: nextKey = 0 # Check if mantissa with next suffix is in range [1, 1000) if abs(val) < 10 ** nextKey and key >= lowest: mantissa, suffix = val / float(10 ** key), negSuffixMap[key] # Do additional step to eliminate results like 0.9999 => 1000m # Check if the key we're potentially switching to is greater than our # upper boundary if nextKey > highest: # If it is, leave loop with results we already have break # Find the multiplier between current and next order orderDiff = 10 ** (nextKey - key) # If rounded mantissa according to our specifications is greater than # or equal to multiplier if roundToPrec(mantissa, prec) >= orderDiff: # Divide mantissa and use suffix of greater order # Use special handling of zero key as it's not on the map mantissa, suffix = mantissa / orderDiff, posSuffixMap[nextKey] if nextKey != 0 else "" # Otherwise consider current results as acceptable break # Round mantissa according to our prec variable mantissa = roundToPrec(mantissa, prec) sign = "+" if forceSign is True and mantissa > 0 else "" # Round mantissa and add suffix if unitName is None: result = "{}{}{}".format(sign, mantissa, suffix) else: result = "{}{} {}{}".format(sign, mantissa, suffix, unitName) return result