Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add random_range functions and code regions #28

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

TehAwesomestKitteh
Copy link
Contributor

@Drillur
Copy link

Drillur commented Feb 15, 2024

I'm on the toilet but I'm 40% sure randomFloatRange will not work as intended! I spent like 6 hours the other day trying to get this to work so consider this:

If you test 1 to 100 a thousand times, I am guessing that 33% of the numbers will be less than 10. That is because when you roll for a random exponent with 1 to 100, it can only be 0, 1, or 2. Each exponent range has a 33% chance to be selected. Therefore... 33% will have an exponent of 0 (less than 10), 33% will have an exponent of 1 (10-99), and 33% will have an exponent of 2 (100-999). Of course, the final thing the function does is normalize(), so it will fix the numbers that are greater than 100! The result is that 66% of numbers are > 10 and 33% are not, when it should be expected that each range of 10 would be 10%.

Hope I said that clearly enough!

@TehAwesomestKitteh
Copy link
Contributor Author

I'm on the toilet but I'm 40% sure randomFloatRange will not work as intended! I spent like 6 hours the other day trying to get this to work so consider this:

If you test 1 to 100 a thousand times, I am guessing that 33% of the numbers will be less than 10. That is because when you roll for a random exponent with 1 to 100, it can only be 0, 1, or 2. Each exponent range has a 33% chance to be selected. Therefore... 33% will have an exponent of 0 (less than 10), 33% will have an exponent of 1 (10-99), and 33% will have an exponent of 2 (100-999). Of course, the final thing the function does is normalize(), so it will fix the numbers that are greater than 100! The result is that 66% of numbers are > 10 and 33% are not, when it should be expected that each range of 10 would be 10%.

Hope I said that clearly enough!

Just tested. randomFloatRange definitely doesn't work as intended. Ran a test of 1 to 100 and it did what you said plus numbers that go over 100. Will try and fix the method and test it thoroughly, then update the branch once I find a better-working solution

@TehAwesomestKitteh
Copy link
Contributor Author

With c01933e, I made it so that if the range being picked from is within 6 decimal places (0-9,999,999), a standard randf_range() is done instead while the minimum exponent is used as a base

Additionally, I added an error check in case someone passes a larger minimum value than the maximum value, reduced the loop presence as a minor optimization, and normalized the result again for randomIntRange in case the number rounded up to a 10 (which is an exponent +1)

That last bit could be improved but with this, randomIntRange and randomFloatRange are working now

@Drillur
Copy link

Drillur commented Feb 15, 2024

if _max.exponent - _min.exponent < 6:
		result.exponent = _min.exponent
		result.mantissa = randf_range(_min.mantissa, 10 ** (_max.exponent - _min.exponent) * _max.mantissa)

When done this way, the mantissa can only ever be greater than min.mantissa. I tested 5 to 100, and all of the numbers were either 5 to 10, or 50 to 100.

@Drillur
Copy link

Drillur commented Feb 15, 2024

I almost feel guilty for dumping this task on your shoulders, lol. You're doing great so far, but it still isn't right!

@Joaopedrocar07031803
Copy link

Joaopedrocar07031803 commented Aug 23, 2024

Friends, here is the solution for you

static func randf_range(a, b):

a = big.new(a)
b = big.new(b)

var ex = randi_range(a.exponent, b.exponent)
print(ex)

var result
if a.exponent == b.exponent:
	result = big.new(randf_range(0, b.mantissa), ex)
	big.normalize(result)
	return result
elif a.exponent != b.exponent:
	if ex == b.exponent:
		result = big.new(randf_range(1, b.mantissa), ex)
		big.normalize(result)
		return result
	elif ex == a.exponent:
		result = big.new(randf_range(a.mantissa, 10.0), ex)
		big.normalize(result)
		return result
	else:
		result = big.new(randf_range(1, 10.0), ex)
		big.normalize(result)
		return result

@Drillur
Copy link

Drillur commented Sep 8, 2024

var ex = randi_range(a.exponent, b.exponent)

Setting the exponent using randi_range is incorrect because it does not take into account the mantissa.

Say A is 9,000 and B is 90,000. The new exponent has a 50% chance to roll 3, and a 50% chance to roll 4. This leads to an inaccurate representation! It should roll an exponent of 3 1,000 out of 100,000 times, or 1% of the time, unless my math is wrong.

This still isn't correct. It needs to incorporate some kind of weight system. I'm going to try to look at it again.

@Drillur
Copy link

Drillur commented Sep 8, 2024

How about this? This seems like it's finally it! I got the base code from Claude and adjusted until it was right. This is passing all of my tests so far. I'm going to use it in my game until I find anything wrong with it.

(By the way, my version of Big is older than the current version, so if y'all want to use this, you will have to adjust it.)

static func rand_range(x: Variant, y: Variant) -> Big:
	var a := Big.new(x)
	var b := Big.new(y)
	
	if a.equal(b):
		return a
	
	# Ensure a < b
	if a.greater(b):
		var temp: Big = b
		b = a
		a = temp
	
	var result: Big
	
	# If a and b are within e10 of each other, calculate it like this
	if absi(b.exponent - a.exponent) <= 10:
		var range := Big.new(b).subtract(a).to_float()
		result = Big.new(randf_range(0.0, range))
		result.add(a)
		return result
	
	var random_exponent := randi_range(a.exponent, b.exponent)
	var random_mantissa: float
	
	if random_exponent == a.exponent:
		random_mantissa = randf_range(a.mantissa, 10.0)
	elif random_exponent == b.exponent:
		random_mantissa = randf_range(1.0, b.mantissa)
	else:
		random_mantissa = randf_range(1.0, 10.0)
	
	result = Big.new(random_mantissa, random_exponent)
	
	# Ensure the result is within the original range (I would guess this would never happen, but what do I know)
	if result.less(a):
		return a
	elif result.greater(b):
		return b
	
	return result

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants