给定基础货币GBP £
,以及商店接受的其他货币表:
Currency Symbol Subunits LastToGBPRate
------------------------------------------------------
US Dollars $ 100 0.592662000
Euros € 100 0.810237000
Japanese Yen ¥ 1 0.005834610
Bitcoin ฿ 100000000 301.200000000
我们有一种工作方法可将GBP Pence (AKA cents)
中的给定金额转换为Currency X cents
。鉴于999(9.99英镑)的价格,对于上述货币,它将返回:
Currency Symbol
---------------------
US Dollars 1686
Euros 1233
Japanese Yen 1755
Bitcoin 3482570
这一切都很好。然后我们有一个Format Currency
方法,将它们全部转换为漂亮的数字:
Currency Formatted
---------------------
US Dollars $16.86
Euros €12.33
Japanese Yen ¥1755
Bitcoin ฿0.03482570
现在我们要解决的问题是,在给定上述信息的情况下,在通用算法中将这些金额舍入到最接近的meaningful pretty number
。
这有两个重要的好处:
meaningful number
是显示的最小单位不小于£0.10的值,pretty number
是以49
或{{1}结尾的单位}。示例输出:
99
我知道可以用一个算法来完成所有这些信息,但是我很难解决从哪里开始的问题。谁能告诉我如何实现这一目标,还是指点一下?
请注意,为每种货币存储一般格式规则是不够的,因为假设比特币10x的价格,格式规则将需要更新。我正在寻找一种不需要任何手动维护/检查的解决方案。
答案 0 :(得分:4)
对于给定的十进制值X,您希望找到最小的整数Y,使得YA + B尽可能接近X,对于某些给定的A和B.在美元的情况下,你有A = .5和B = .49。
一般来说,对于您的问题,A和B可以通过以下公式计算:
V = value of £0.10 in target currency
K = smallest power of ten (10^k) such that 9*10^k >= V
and k <= -2 (this condition I added based on your examples, but contrary
to your definition)
= 10^min(-2, ceil(log10(V / 9)))
A = 50 * K
B = 49 * K
请注意,如果没有额外条件,因为0.09美元小于0.10磅,我们将得到14.9,结果为16.86美元。
通过一些转变我们得到了
Y ~ (X - B) / A
由于Y是整数,我们有
Y = round((X - B) / A)
结果是YA + B.
答案 1 :(得分:1)
将£0.10
转换为当前货币以确定最小可显示数字(SDD)
(以该货币的可用数字数量为限)。
现在我们基本上有3种数字选择:
... (3rdSDD-1) 9 9
(如果3rdSDD
为0,则显然会从4thSDD
开始,依此类推,因为减法通常有效)
我们会在10*2ndSDD + 1stSDD < 24
... 3rdSDD 4 9
我们会在24 <= 10*2ndSDD + 1stSDD < 74
... 3rdSDD 9 9
我们会在74 < 10*2ndSDD + 1stSDD
从这里弄清楚它应该是微不足道的
一些乘法和模数可以得到2ndSDD
和1stSDD
基本的减法可以让你... (3rdSDD-1)
一些if语句可以选择上述案例之一。
示例:强>
对于$16.86
,我们的3个选项为$15.99
,$16.49
和$16.99
。
我们从$16.99
开始选择74 < 86
。
对于€12.33
,我们的3个选项为€11.99
,€12.49
和€12.99
。
我们从€12.49
开始选择24 <= 33 < 74
。
对于¥1755
,我们的3个选项为¥1699
,¥1749
和¥1799
。
我们从¥1749
开始选择24 <= 55 < 74
。
对于฿0.03482570
,我们的3个选项为฿0.0299
,฿0.0349
和฿0.0399
。
我们从฿0.0349
开始选择24 <= 48 < 74
。
而且,只是为了显示进位:
对于$100000.23
,我们的3个选项为$99999.99
,$100000.49
和$100000.99
。
我们从$99999.99
开始选择23 < 24
。
答案 2 :(得分:1)
这是一个难看的答案:
def retail_round(number):
"""takes a decimal.Decimal and retail rounds it"""
ending_digits = str(number)[-2:]
if not ending_digits in ("49","99"):
rounding_adjust = (99 - int(ending_digits)) % 50
if rounding_adjust <= 25:
number = str(number)[:-2]+str(int(ending_digits)+int(rounding_adjust))
else:
if str(number)[-3] == '.':
number = str(int(number) - .01)
else:
number = str(int(str(number)[:-2]+"00")-1)
return decimal.Decimal(number)
>>> import decimal
>>> retail_round(decimal.Decimal("15.50"))
Decimal('14.99')
>>> retail_round(decimal.Decimal("15.51"))
Decimal('14.99')
>>> retail_round(decimal.Decimal("15.75"))
Decimal('15.99')
>>> retail_round(decimal.Decimal("1575"))
Decimal('1599')
>>> retail_round(decimal.Decimal("1550"))
Decimal('1499')
编辑:这是一个更好的解决方案,使用decimal.Decimal
Currency = collections.namedtuple("Currency",["name","symbol",
"subunits"])
def retail_round(currency, amount):
"""returns a decimal.Decimal amount of the currency, rounded to
49 or 99."""
adjusted = ( amount / currency.subunits ) % 100 # last two digits
print(adjusted)
if adjusted < 24:
amount -= (adjusted + 1) * currency.subunits # down to 99
elif 24 <= adjusted < 74:
amount -= (adjusted - 49) * currency.subunits # to 49
else:
amount -= (adjusted - 99) * currency.subunits # up to 99
return amount
答案 3 :(得分:-1)
例如:£0.10 = 17.1421309¥
log(17.1421309) = 1.234
ceil(1.234) = 2
10^2 = 100
so
¥174055 will be ¥174900
调整数字的数字,加1,舍入为50,减去1:
174055 - &gt; (round((174055/100 + 1)/ 50)* 50-1)* 100 = 174900
简单明了。