2

I'm trying to represent number in Indian/US notation but the value I give and the output are not the same. Please check the code.

import locale
result = 1
for i in range(1,65):
    result = result*i
print (result)

output: 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000

print(f'{result:,}')

output: 126,886,932,185,884,164,103,433,389,335,161,480,802,865,516,174,545,192,198,801,894,375,214,704,230,400,000,000,000,000

locale.setlocale(locale.LC_MONETARY, 'en_IN')
print(locale.currency(result, grouping=True))

output:₹1,26,88,69,32,18,58,84,16,54,37,80,68,97,58,51,22,92,52,90,11,90,29,06,47,05,20,97,78,50,85,45,10,34,77,59,05,11,63,70,67,40,17,89,440.00

locale.setlocale(locale.LC_MONETARY, 'en_US')
print(locale.currency(result, grouping=True))

output:$126,886,932,185,884,165,437,806,897,585,122,925,290,119,029,064,705,209,778,508,545,103,477,590,511,637,067,401,789,440.00

if you notice with print(f'{result:,}') the value of result does not change, but the problem is with locale package where the result and output changes from 12688693218588416.

Questions:

1.Why does the value change?

2.How to correct this?

Hathick
  • 33
  • 1
  • 6
  • 1
    Commas aren't used to represent spacing within numbers. Try using underscore (`_`) – A random coder May 13 '21 at 14:13
  • 1
    @Arandomcoder OP isn't trying to represent spacing with commas, those values are what Python is printing out using localization. – MattDMo May 13 '21 at 14:14
  • Ah, i see now. Thanks for the clarification @MattDMo – A random coder May 13 '21 at 14:14
  • 3
    `locale.currency()` is apparently converting your value to a float - which only has about 16 digits of precision. – jasonharper May 13 '21 at 14:17
  • 1
    I'm guessing the problem is related to conversion to floats, which is inherently imprecise. See https://stackoverflow.com/a/20980470/874188 and http://stackoverflow.com/questions/588004/ddg#588014 – tripleee May 13 '21 at 14:19

1 Answers1

2

It looks like locale.currency() is casting your input to float. I don't know how to fix that, but you might use this alternative:

import locale

def big_money(val, loc):
    locale.setlocale(locale.LC_MONETARY, loc)
    retval = locale.localeconv()["currency_symbol"] + locale.format_string("%i", val, grouping=True, monetary=True)
    locale.setlocale(locale.LC_MONETARY, "")
    return retval

result = 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000

print(big_money(result, "en_IN"))
print(big_money(result, "en_US"))

That gives me:

?1,26,88,69,32,18,58,84,16,41,03,43,33,89,33,51,61,48,08,02,86,55,16,17,45,45,19,21,98,80,18,94,37,52,14,70,42,30,40,00,00,00,00,00,000
$126,886,932,185,884,164,103,433,389,335,161,480,802,865,516,174,545,192,198,801,894,375,214,704,230,400,000,000,000,000

Actually reflecting on this, I don't think this method should mess with the local at all so use:

import locale

def big_money(val):
    return locale.localeconv()["currency_symbol"] + locale.format_string("%i", val, grouping=True, monetary=True)

result = 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000

locale.setlocale(locale.LC_MONETARY, "en_IN")
print(big_money(result))

locale.setlocale(locale.LC_MONETARY, "en_US")
print(big_money(result))

In the end you still get:

?1,26,88,69,32,18,58,84,16,41,03,43,33,89,33,51,61,48,08,02,86,55,16,17,45,45,19,21,98,80,18,94,37,52,14,70,42,30,40,00,00,00,00,00,000
$126,886,932,185,884,164,103,433,389,335,161,480,802,865,516,174,545,192,198,801,894,375,214,704,230,400,000,000,000,000
JonSG
  • 10,542
  • 2
  • 25
  • 36