Repository: litestar-org/polyfactory (python)

Issue:
`create_random_float` creates extremely constrained floats without maximum
Without `maximum`, floats are extremely constrained:

```
>>> create_random_float(Random(), minimum=100, maximum=None)
100.18084162477052
>>> create_random_float(Random(), minimum=100, maximum=None)
100.54924103325709
>>> create_random_float(Random(), minimum=100, maximum=None)
101.5380217963041
>>> create_random_float(Random(), minimum=100, maximum=None)
100.48749377309393
>>> create_random_float(Random(), minimum=100, maximum=None)
100.62887519044165
```

With `maximum`, they are differentiated much more:

```
>>> create_random_float(Random(), minimum=100, maximum=1000)
922.9521500077755
>>> create_random_float(Random(), minimum=100, maximum=1000)
594.5901441349624
>>> create_random_float(Random(), minimum=100, maximum=1000)
668.6168721529523
>>> create_random_float(Random(), minimum=100, maximum=1000)
760.5950727117361
>>> create_random_float(Random(), minimum=100, maximum=1000)
269.2787865511392
```

I discovered this while debugging a factory of mine. It's a `ModelFactory` (Pydantic), with a `PositiveInt` field (built-in Pydantic type), and I found that Polyfactory barely differentiated those ints. I traced that to the `create_random_float` function, and values passed to it. 

Pull request:
feat: improve random range
<!--
By submitting this pull request, you agree to:
- follow [Litestar's Code of Conduct](https://github.com/litestar-org/.github/blob/main/CODE_OF_CONDUCT.md)
- follow [Litestar's contribution guidelines](https://github.com/litestar-org/.github/blob/main/CONTRIBUTING.md)
- follow the [PSFs's Code of Conduct](https://www.python.org/psf/conduct/)
-->
## Description

Based on existing implementation and raised issue this feels like a better range and closer to intention.

<!--
Please add in issue numbers this pull request will close, if applicable
Examples: Fixes #4321 or Closes #1234

Ensure you are using a supported keyword to properly link an issue:
https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword
-->
## Closes

Fixes #645

Patch:
diff --git a/polyfactory/value_generators/primitives.py b/polyfactory/value_generators/primitives.py
index 2cf6b41..b2f280e 100644
--- a/polyfactory/value_generators/primitives.py
+++ b/polyfactory/value_generators/primitives.py
@@ -22,9 +22,12 @@ def create_random_float(
     :returns: A random float.
     """
     if minimum is None:
-        minimum = float(random.randint(0, 100)) if maximum is None else float(maximum) - 100.0
+        if maximum is None:
+            minimum = float(random.randint(0, 100))
+        else:
+            minimum = float(maximum) / 2 if maximum >= 0 else float(maximum) * 2.0
     if maximum is None:
-        maximum = float(minimum) + 1.0 * 2.0 if minimum >= 0 else float(minimum) + 1.0 / 2.0
+        maximum = (float(minimum) + 1.0) * 2.0 if minimum >= 0 else (float(minimum) + 1.0) / 2.0
     return random.uniform(float(minimum), float(maximum))
 
 


Test patch:
diff --git a/tests/constraints/test_int_constraints.py b/tests/constraints/test_int_constraints.py
index 13e1714..9a5efaf 100644
--- a/tests/constraints/test_int_constraints.py
+++ b/tests/constraints/test_int_constraints.py
@@ -205,17 +205,9 @@ def test_handle_constrained_int_handles_multiple_of_with_ge_and_le(val1: int, va
 
 def test_constraint_randomness() -> None:
     random = Random(10)
-    result = handle_constrained_int(
-        random=random,
-    )
-    assert result == 55
-
-    result = handle_constrained_int(
-        random=random,
-    )
-    assert result == 61
-
-    result = handle_constrained_int(
-        random=random,
-    )
-    assert result == 85
+    assert [
+        handle_constrained_int(
+            random=random,
+        )
+        for _ in range(3)
+    ] == [81, 109, 152]
diff --git a/tests/test_number_generation.py b/tests/test_number_generation.py
index 4800ecc..d43b7f1 100644
--- a/tests/test_number_generation.py
+++ b/tests/test_number_generation.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
 from random import Random
 
 import pytest
@@ -26,5 +28,27 @@ def test_generate_constrained_number(maximum: float, minimum: float, multiple_of
     )
 
 
+@pytest.mark.parametrize(
+    "minimum, maximum",
+    (
+        (None, None),
+        (-200, None),
+        (200, None),
+        (None, -200),
+        (None, 200),
+        (-200, 200),
+    ),
+)
+def test_create_random_float_bounds(
+    minimum: float | None,
+    maximum: float | None,
+) -> None:
+    result = create_random_float(Random(), minimum, maximum)
+    if minimum is not None:
+        assert result >= minimum
+    if maximum is not None:
+        assert result <= maximum
+
+
 def test_passes_pydantic_multiple_validator_handles_zero_multiplier() -> None:
     assert passes_pydantic_multiple_validator(1.0, 0)