Python Forum

Full Version: Conceptualizing modulus. How to compare & communicate with values in a Dictionary
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello all

I have two questions

The first is why one change calculator works and the other doesn't.

The second question is about how to efficiently communicate and compare dictionary values while citing who they belong to.

Starting with the first you have two change calculator programs

Program A this functions

currency=float(input("enter value in $- "))
currency=currency*100
dollar=int(currency/100)
print("dollar-",dollar)
ra=currency%100
#print(ra)
quarters=int(ra/25)
print("quarters-",quarters)
ra=int(ra%25)
#print(ra))
dimes=int(ra/10)
print("dime-",dimes)
ra=int(ra%10)
#print(ra)
nickel=int(ra/5)
print("nickel-",nickel)
ra=int(ra%5)
#print(ra)
penny=int(ra/1)
print("penny-",penny)
Program B this partially functions
dollar=1
quarter=.25
dime=.10
nickel=.05
penny=.01
total=float(input("Enter the total amount: "))
print("The total can be reduced to")
print (int(total/dollar),"Dollars") #Amount of dollars
total = total%dollar
print (int(total/quarter),"Quarters") #Amount of quarters
total = total%quarter
print (int(total/dime),"Dimes") #Amount of dimes
total = total%dime
print (int(total/nickel),"Nickel") #Amount of nickel
total = total%nickel
print (int(total/penny),"Pennies") #Amount of pennies
I'm looking for a simple solution to fix the second program. I think the flaw is related to how I was programming blind with the mod operator. Modding a smaller number against a larger one like in this example
https://visualfractions.com/calculator/m...s-3-mod-5/
Where 3 mod 5 is 3 is over my head logic for now. I could probably watch a video and understand how it works so this isn't really my question but I think its related to my ignorance. What I'm really asking is why does the first program work and not the second and if there a simple way to fix the second program or am I chasing a waterfall trying to use that method?


The second question is a little simpler to ask.

I'm trying to count NPCs in a dictionary and compare their values while citing who they are. So far I have the count right but comparing the values and citing who they belong too has been a Sick Sick .


dictStudents={'001':['Grex','22','40'], '002':['C-Paul','02' ,'88'], '003':['Aquille','11','76']}  
dictionary_length = len(dictStudents)
print('The school has:',dictionary_length,'students.')

maximum = max(dictStudents[2], key=dictStudents[2].get) 
print(maximum, dictStudents[2][maximum])
___
These are total personality and ability scores next to names.

How would I print that C-Paul has the highest ability score with 88 or that Grex has the highest personality score with 22? I have found ways where I can identify the max of all values. I'm trying to compare specific values and identify the person who has it. I'm also wondering if I can name the values and reference the values by whatever variable or name so its ['Name','personality' ,'ability']?
You don't mention what's wrong with the second. You should give an example input, what the expected output is, and how this one differs. When I tried an input, it seemed okay.

That said, your first program is working with integers while the second calculator is working with floats. That can cause problems if you're not ready for it because the division can be imprecise. If you're dealing with coins, much better to work in integer cents rather than fractional dollars.
Can you give an example of why program B does not work when program A does.
Sometimes the float precision causes int(total/value) to miss a penny. For example, 0.09 is 1 nickel and 3 pennies because 0.09 % 0.05 is 0.0399999999999994.

I wrote a little program that calculates change and converts the change back into a float. If the initial value does not equal the total value, I print the numbers and the change.
coins = (1, 0.25, 0.1, 0.05, 0.01)

def change(total):
    result = []
    for coin in coins:
        result.append(int(total / coin))
        total = total % coin
    return result

def total(change):
    result = 0
    for coin, count in zip(coins, change):
        result += int(coin * 100) * count
    return result

for i in range(0, 201):
    c = change(i/100)
    v = total(c)
    if i != v:
        print(i, v, c)
Output:
6 5 [0, 0, 0, 1, 0] 9 8 [0, 0, 0, 1, 3] 11 10 [0, 0, 1, 0, 0] 12 11 [0, 0, 1, 0, 1] 15 14 [0, 0, 1, 0, 4]
Sometimes we lose a penny.

A way to fix this is round the result of the modulo operation.
coins = (1, 0.25, 0.1, 0.05, 0.01)

def change(total):
    result = []
    for coin in coins:
        result.append(int(total / coin))
        total = round(total % coin, 2)
    return result

def total(change):
    result = 0
    for coin, count in zip(coins, change):
        result += int(coin * 100) * count
    return result

for i in range(0, 201):
    c = change(i/100)
    v = total(c)
    if i != v:
        print(i, v, c)
Giving change is perhaps a use case where the Decimal class is more appropriate than float. For example
>>> import decimal
>>> D = decimal.Decimal
>>> 
>>> D('0.09') % D('0.05')
Decimal('0.04')
>>> divmod(D('0.09'), D('0.05'))
(Decimal('1'), Decimal('0.04'))
(Feb-25-2021, 08:49 PM)bowlofred Wrote: [ -> ]You don't mention what's wrong with the second. You should give an example input, what the expected output is, and how this one differs. When I tried an input, it seemed okay.

The problem with the second program is I don't know where to begin after the first part. The first part is ok. I'm able to count the dictionary entries and I'm good with the code. Finding an efficient way to compare the entries with an output that references the individual by name, states that they have the highest value and tags or names the actual value has been a problem. Normally I can do an internet search and find out how to do something like that and I did come close but the solution seemed inefficient and didn't understand it completely.

Thanks for the response btw. Its appreciated.

Gribouillis, deanhystad
That answers the first question. I switched int to float and I could see how I was losing a penny but I didn't know why and what to do about it but I do now so thanks.
To find highest and lowest, sort them.
x = {'001':['Grex','22','40'], '002':['C-Paul','02' ,'88'], '003':['Aquille','11','76']}

print('By Name', dict(sorted(x.items(), key=lambda item: item[1])))

print('By Personality', dict(sorted(x.items(), key=lambda item: item[1][1])))

print('By Ability', dict(sorted(x.items(), key=lambda item: item[1][2])))
As for efficient access, maybe you want to create 2 dictionaries. One keyed by ID ('001?) and another by name.
Thanks. deanhystad
Wow I was really overthinking it.