Returning 1.0 when appropriate isn’t a problem, though. Many representable floats near pi/2 deliver exactly 1.0 when passed to sin().
The reason: apart from signs, sin and cos are the derivatives of each other. So when one is at an extreme value, the other is very close to 0, and the function value changes very slowly when the derivative is near 0,. 1.0 is “very” large compared to the derivative then.
>>> import math
>>> x = math.pi / 2
>>> x
1.5707963267948966
>>> math.sin(x)
1.0
>>> u = math.ulp(x)
>>> u
2.220446049250313e-16
>>> math.sin(x + 1e6 * u)
1.0
>>> math.sin(x - 1e6 * u)
1.0
So not only is sin() exactly 1.0 at the machine value of pi/2, at remains 1.0 at a million ulp on both sides of pi/2. It’s already numerically very stable. At a billion ulp, the difference becomes quite noticeable, but still relatively small:
>>> math.sin(x + 1e9 * u)
0.9999999999999754
The flip side is that one is near zero, the other is at an extreme value, and with the derivative being as large as possible, the function’s value is very sensitive to the tiniest changes.