Generation of random numbers a, b, c such that a ^ 2 + b ^ 2 + c ^ 2 = 1

To do some simulations in Python, I'm trying to generate numbers a, b, c such that a^2 + b^2 + c^2 = 1. I think creating a few abetween 0 and 1, then some bbetween 0 and sqrt(1 - a^2), and then c= sqrt(1 - a^2 - b^2)will work.

Floating-point values ​​are accurate, the sum of the squares should be close to 1. I want to save them for some iterations.

Being new to Python, I'm not sure how to do this. Negative values ​​are allowed.

Edit: Thanks so much for the answers!

+6
source share
6 answers

"" , - . , cos(theta), "" . , " " , :

x = np.random.uniform(0,1,3) # random numbers in [0, 1)
x /= np.sqrt(x[0] ** 2 + x[1] ** 2 + x[2] ** 2)

, , numpy, , x = np.random.uniform(0, 1, (3, n)) n.

+3

, , :

import numpy as np
import random
import math

def MSeifert():
    a = 1
    b = 1
    while a**2 + b**2 > 1:  # discard any a and b whose sum of squares already exceeds 1
        a = random.random()
        b = random.random()
    c = math.sqrt(1 - a**2 - b**2)  # fixed c
    return a, b, c

def VBB():
    x = np.random.uniform(0,1,3) # random numbers in [0, 1)
    x /= np.sqrt(x[0] ** 2 + x[1] ** 2 + x[2] ** 2)
    return x[0], x[1], x[2]

def user3684792():
    theta = random.uniform(0, 0.5*np.pi)
    phi = random.uniform(0, 0.5*np.pi)
    return np.sin(theta)* np.cos(phi), np.sin(theta)*np.sin(phi), np.cos(theta)

def JohanL():
    abc = np.random.normal(size=3)
    a,b,c = abc/np.sqrt(sum(abc**2))
    return a, b, c

def SeverinPappadeux():
    cos_th = 2.0*random.uniform(0, 1.0) - 1.0
    sin_th = math.sqrt(1.0 - cos_th*cos_th)
    phi = random.uniform(0, 2.0*math.pi)
    return sin_th * math.cos(phi), sin_th * math.sin(phi), cos_th

:

%matplotlib notebook

import matplotlib.pyplot as plt

f, axes = plt.subplots(3, 4)

for func_idx, func in enumerate([MSeifert, JohanL, user3684792, VBB]):
    axes[0, func_idx].set_title(str(func.__name__))
    res = [func() for _ in range(50000)]
    for idx in range(3):
        axes[idx, func_idx].hist([i[idx] for i in res], bins='auto')

axes[0, 0].set_ylabel('a')
axes[1, 0].set_ylabel('b')
axes[2, 0].set_ylabel('c')

plt.tight_layout()

:

enter image description here

: a, b c , () .

, (-1, 1), JohanLs Severin Pappadeux. , [0, 1). , -1 1, 0 1.

+8

stats.stackexchange.com, . , :

import numpy as np
abc = np.random.normal(size=3)
a,b,c = abc/np.sqrt(sum(abc**2))
+7

, , - .

import random
import numpy as np
def random_pt():
    theta = random.uniform(0, 0.5*np.pi)
    phi = random.uniform(0, 0.5*np.pi)
    return np.sin(theta)* np.cos(phi), np.sin(theta)*np.sin(phi), np.cos(theta)
+6

:

import random
import math

def three_random_numbers_adding_to_one():
    a = 1
    b = 1
    while a**2 + b**2 > 1:  # discard any a and b whose sum of squares already exceeds 1
        a = random.random()
        b = random.random()
    c = math.sqrt(1 - a**2 - b**2)  # fixed c
    return a, b, c

a, b, c = three_random_numbers_adding_to_one()
print(a**2 + b**2 + c**2)

float , 1.

, , , "". , "".

+4

, ...

- http://mathworld.wolfram.com/SpherePointPicking.html

import math
import random

def random_pt():
    cos_th = 2.0*random.uniform(0, 1.0) - 1.0
    sin_th = math.sqrt(1.0 - cos_th*cos_th)
    phi = random.uniform(0, 2.0*math.pi)
    return sin_th * math.cos(phi), sin_th * math.sin(phi), cos_th

for k in range(0, 100):
    a, b, c = random_pt()

    print("{0} {1} {2} {3}".format(a, b, c, a*a + b*b + c*c))
+3
source

All Articles