# Precision issue when using numpy.sin

I am trying to generate a square wave starting from a sine wave using numpy.
I ran into a problem where:

• using the `numpy.pi` constant gives inaccurate results
• using the `3.14` constant gives me the correct result

To create the square wave the sign of the sine wave is taken and then the -1s are transformed into 0s using the maximum function.

``````N = 15
x = np.arange(1, N)
s = np.maximum(np.sign(np.sin(3.14 * (x - 1))), np.zeros_like(x))
print(s)

>> [0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1.]
``````

While using the constant for pi in numpy gives:

``````N = 15
x = np.arange(1, N)
s = np.maximum(np.sign(np.sin(np.pi * (x - 1))), np.zeros_like(x))
print(s)

>> [0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 0.]
``````

where the sequence is not alternating 1s and 0s. With more elements you can observe patches of more than two 0s next to each other.

``````[0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 1. 0. 0. 0. 1. 0. 0. 0.]
``````

I am mostly trying to understand how using more precise values can lead to imprecise results.

### >Solution :

Your computation is numerically unstable. Using a higher precision will not solve the problem but just hide it a little bit more. The main issue is that `sin(PI * x)` should be theoretically always 0, but no floating-point function is perfect, so there is an error (typically 1 ULP). This error change the sign of the result. This is what you observe. This problem is independent of the precision. Here is a geometrical illustration of what you compute: If you just want alternated 0-1 values, you can add a shift to the `sin` function (eg. `np.maximum(np.sign(np.sin(np.pi * (x - 1) + np.pi/2)), np.zeros_like(x))`). If the shift is `pi/2`, then you can use a `cos` function.