I have a rather gnarly bit of code that must more-or-less randomly generate a bunch of percentages, stored as decimal floats. That is, it decides that material one makes up 13.307 percent of the total, then stores that in a dict as 0.13307.
The trouble is, I can never get those numbers to add up to exactly one. I'm not entirely certain what the problem is, honestly. It might be something to do with the nature of floats.
Here's the offending code, in all its overcomplicated glory:
while not sum(atmosphere.values())>=1:
#Choose a material randomly
themat=random.choice(list(materials.values()))
#If the randomly chosen material is gaseous at our predicted temperature...
if themat.vapor < temp:
#Choose a random percentage that it will make up of our planet's atmosphere, then put it in the atmos dict.
atmosphere[themat]=round(random.uniform(0.001,0.5),5)
#Find out if the fractions add up to more than 1
difference=(sum(atmosphere.values())-1)
#If one does...
while difference > 0:
#Choose a random constituent
themat=random.choice(list(atmosphere.keys()))
#If that constituent has a higher fraction value than the amount we'd need to reduce the total to 1...
if atmosphere[themat]>(sum(atmosphere.values())-1):
#Subtract that much from it.
atmosphere[themat]-=difference
#Then break the loop, since we're done and otherwise we'd go on removing bits of the atmosphere forever.
break
else:
#Otherwise, halve its percentage and reduce difference by the amount we reduced the atmosphere
oldperc=atmosphere[themat]
atmosphere[themat]=oldperc/2
difference-=oldperc/2
#Then, finally, we correct any overcorrections the previous block made.
difference=(sum(atmosphere.values())-1)
if difference < 0:
#Choose a random mat
themat=random.choice(list(atmosphere.keys()))
#Then add enough to it that the total is 1.
atmosphere[themat]+=difference
Sorry if I've missed something obvious, or am not providing an important bit of information, but I'm tired at the moment, and I've been trying to figure this out for days now.