我有两个相等的向量V1和V2
x * V1 = V2
当我需要确定x时,V1和V2都是已知的。我也确切地知道有一个x可以解决这个问题。
我可以用手工建立一个方程组来获得x。事实上,我不需要进行任何高斯消除,因为它是如此简单的设置。这导致我尝试x = V2.x / V1.x.然而,这可能导致除以零。
我是用C ++写的,如果这很重要的话。
谢谢!
答案 0 :(得分:1)
作为我自己问题的答案
x =(V2.x + V2.y + V2.z)/(V1.x + V1.y + V1.z)
如果V1全为零,那将无法工作,但在我的情况下不会发生这种情况。
答案 1 :(得分:1)
怎么样:
double getX(const std::vector<double>& V1, const std::vector<double>& V2) {
if (V1.size() != V2.size()) return 0;
for( int i=0; i<V1.size(); i++ ){
if(V1[i] != 0) {
return v2[i] / v1[i];
}
}
return 0;
}
答案 2 :(得分:1)
提问者自己的解决方案存在缺陷,因为如果(V1.x + V1.y + V1.z)加起来它会失败:
x =(V2.x + V2.y + V2.z)/(V1.x + V1.y + V1.z)
以下是此问题的正确解决方案:
path.data: /data1/es1,/data2/es1,/data3/es1
答案 3 :(得分:0)
只需循环通过V1的坐标,找到第一个非零,然后除。
答案 4 :(得分:0)
我的一个数学库的旧版本中有几个类。我不再特别使用它们了,因为我最近一直在使用GLM数学库,但为了这个答案的目的,他们将展示所需要的东西。
GeneralMath.h - 执行基本数学运算需要此通用数学类。
#ifndef GENERALMATH_H
#define GENERALMATH_H
#include "stdafx.h"
class Math {
public:
static const float PI;
static const float PI_HALVES;
static const float PI_THIRDS;
static const float PI_FOURTHS;
static const float PI_SIXTHS;
static const float PI_2;
static const float PI_INVx180;
static const float PI_DIV180;
static const float PI_INV;
static const float ZERO;
Math();
inline static bool isZero( float fValue );
inline static float sign( float fValue );
inline static int randomRange( int iMin, int iMax );
inline static float randomRange( float fMin, float fMax );
inline static float degree2Radian( float fDegrees );
inline static float radian2Degree( float fRadians );
inline static float correctAngle( float fAngle, bool bDegrees, float fAngleStart = 0.0f );
inline static float mapValue( float fMinY, float fMaxY, float fMinX, float fMaxX, float fValueX );
template<class T>
inline static void constrain( T min, T max, T &value );
template<class T>
inline static void swap( T &value1, T &value2 );
}; // Math
// -----------------------------------------------------------------------
// degree2Radian()
// Convert Angle In Degrees To Radians
inline float Math::degree2Radian( float fDegrees ) {
return fDegrees * PI_DIV180;
} // degree2Radian
// -----------------------------------------------------------------------
// radian2Degree()
// Convert Angle In Radians To Degrees
inline float Math::radian2Degree( float fRadians ) {
return fRadians * PI_INVx180;
} // radian2Degree
// -----------------------------------------------------------------------
// correctAngle()
// Returns An Angle Value That Is Alway Between fAngleStart And fAngleStart + 360
// If Radians Are Used, Then Range Is fAngleStart To fAngleStart + 2PI
inline float Math::correctAngle( float fAngle, bool bDegrees, float fAngleStart ) {
if ( bDegrees ) {
// Using Degrees
if ( fAngle < fAngleStart ) {
while ( fAngle < fAngleStart ) {
fAngle += 360.0f;
}
}
else if ( fAngle >= (fAngleStart + 360.0f) ) {
while ( fAngle >= (fAngleStart + 360.0f) ) {
fAngle -= 360.0f;
}
}
return fAngle;
}
else {
// Using Radians
if ( fAngle < fAngleStart ) {
while ( fAngle < fAngleStart ) {
fAngle += Math::PI_2;
}
}
else if ( fAngle >= (fAngleStart + Math::PI_2) ) {
while ( fAngle >= (fAngleStart + Math::PI_2) ) {
fAngle -= Math::PI_2;
}
}
return fAngle;
}
} // correctAngle
// -----------------------------------------------------------------------
// isZero()
// Tests If Input Value Is Close To Zero
inline bool Math::isZero( float fValue ) {
if ( (fValue > -ZERO) && (fValue < ZERO) ) {
return true;
}
return false;
} // isZero
// -----------------------------------------------------------------------
// sign()
// Returns 1 If Value Is Positive, -1 If Value Is Negative Or 0 Otherwise
inline float Math::sign( float fValue ) {
if ( fValue > 0 ) {
return 1.0f;
}
else if ( fValue < 0 ) {
return -1.0f;
}
return 0;
} // sign
// -----------------------------------------------------------------------
// randomRange()
// Return A Random Number Between iMin And iMax Where iMin < iMax
// NOTE: This function is quite old; haven't had time to update the random number generator system
inline int Math::randomRange( int iMin, int iMax ) {
if ( iMax < iMin ) {
swap( iMax, iMin );
}
return (iMin + ((iMax - iMin +1) * rand()) / (RAND_MAX+1) );
} // randomRange
// -----------------------------------------------------------------------
// randomRange()
// Return A Random Number Between fMin And fMax Where fMin < fMax
// NOTE: This function is quite old; haven't had time to update the random number generator system
inline float Math::randomRange( float fMin, float fMax ) {
if ( fMax < fMin ) {
swap( fMax, fMin );
}
return (fMin + (rand()/(float)RAND_MAX)*(fMax-fMin));
} // randomRange
// -----------------------------------------------------------------------
// mapValue()
// Returns The fValueY That Corresponds To A Point On The Line Going From Min To Max
inline float Math::mapValue( float fMinY, float fMaxY, float fMinX, float fMaxX, float fValueX ) {
if ( fValueX >= fMaxX ) {
return fMaxY;
}
else if ( fValueX <= fMinX ) {
return fMinY;
}
else {
float fM = (fMaxY - fMinY) / (fMaxX - fMinX);
float fB = fMaxY - fM * fMaxX;
return (fM*fValueX + fB);
}
} // mapValue
// -----------------------------------------------------------------------
// constrain()
// Prevent Value From Going Outside The Min, Max Range.
template<class T>
inline void Math::constrain( T min, T max, T &value ) {
if ( value < min ) {
value = min;
return;
}
if ( value > max ) {
value = max;
}
} // constrain
// -----------------------------------------------------------------------
// swap()
template<class T>
inline void Math::swap( T &value1, T &value2 ) {
T temp;
temp = value1;
value1 = value2;
value2 = temp;
} // swap
#endif // GENERALMATH_H
<强> GeneralMath.cpp 强>
#include "stdafx.h"
#include "GeneralMath.h"
const float Math::PI = 4.0f * atan(1.0f); // tan(pi/4) = 1
const float Math::PI_HALVES = 0.50f * Math::PI;
const float Math::PI_THIRDS = Math::PI * 0.3333333333333f;
const float Math::PI_FOURTHS = 0.25f * Math::PI;
const float Math::PI_SIXTHS = Math::PI * 0.6666666666667f;
const float Math::PI_2 = 2.00f * Math::PI;
const float Math::PI_DIV180 = Math::PI / 180.0f;
const float Math::PI_INVx180 = 180.0f / Math::PI;
const float Math::PI_INV = 1.0f / Math::PI;
const float Math::ZERO = (float)1e-7;
// -----------------------------------------------------------------------
// Math()
// Default Constructor
Math::Math() {
} // Math
<强> Vector3.h 强>
#ifndef VECTOR3_H
#define VECTOR3_H
#include "stdafx.h"
#include "GeneralMath.h"
class Vector3 {
public:
union {
float m_f3[3];
struct {
float m_fx;
float m_fy;
float m_fz;
};
};
inline Vector3();
inline Vector3( float x, float y, float z );
inline Vector3( float *pfv );
~Vector3();
// Operators
inline Vector3 operator+( const Vector3 &v3 ) const;
inline Vector3 operator+() const;
inline Vector3& operator+=( const Vector3 &v3 );
inline Vector3 operator-( const Vector3 &v3 ) const;
inline Vector3 operator-() const;
inline Vector3& operator-=( const Vector3 &v3 );
inline Vector3 operator*( const float &fValue ) const;
inline Vector3& operator*=( const float &fValue );
inline Vector3 operator/( const float &fValue ) const;
inline Vector3& operator/=( const float &fValue );
// -------------------------------------------------------------------
// operator*()
// Pre Multiple Vector By A Scalar
inline friend Vector3 Vector3::operator*( const float &fValue, const Vector3 v3 ) {
return Vector3( fValue*v3.m_fx, fValue*v3.m_fy, fValue*v3.m_fz );
} // operator*
// -------------------------------------------------------------------
// operator/()
// Pre Divide Vector By A Scalar Value
inline friend Vector3 Vector3::operator/( const float &fValue, const Vector3 v3 ) {
Vector3 vec3;
if ( Math::isZero( v3.m_fx ) ) {
vec3.m_fx = 0.0f;
} else {
vec3.m_fx = fValue / v3.m_fx;
}
if ( Math::isZero( v3.m_fy ) ) {
vec3.m_fy = 0.0f;
} else {
vec3.m_fy = fValue / v3.m_fy;
}
if ( Math::isZero( v3.m_fz ) ) {
vec3.m_fz = 0.0f;
} else {
vec3.m_fz = fValue / v3.m_fz;
}
return vec3;
} // operator/
// -----------------------------------------------------------------
// operator/()
// Divide Vector by Vector component wise returns scalar value.
inline friend float Vector3::operator/( const Vector3& v1, const Vector3& v2 ) {
if ( Math::isZero( v2.m_fx ) ||
Math::isZero( v2.m_fy ) ||
Math::izZero( v2.m_fz ) ) {
throw ( std::string( "Divide by Zero" ) );
}
float val = v1.m_fx / v2.m_fx;
if ( (val == (v1.m_fy / v2.m_fy) ) &&
(val == (v1.m_fz / v2.m_fz) ) ) {
return val;
}
} // operator/
// Functions
inline float divideByVector( const Vector3& v );
inline Vector3 rotateX( float fRadians );
inline Vector3 rotateY( float fRadians );
inline Vector3 rotateZ( float fRadians );
inline void setPerpendicularXZ( Vector3 v3 );
inline void setPerpendicularXY( Vector3 v3 );
inline void setPerpendicularYZ( Vector3 v3 );
inline Vector3 cross( const Vector3 v3 ) const;
inline float dot( const Vector3 v3 ) const;
inline float getAngle( const Vector3 &v3, const bool bNormalized = false, bool bRadians = true );
inline float getCosAngle( const Vector3 &v3, const bool bNormalized = false );
inline float length() const;
inline float length2() const;
inline void normalize();
inline void zero();
inline bool isZero() const;
}; // Vector3
// -----------------------------------------------------------------------
// Vector3()
// Constructor
inline Vector3::Vector3() :
m_fx( 0.0f ),
m_fy( 0.0f ),
m_fz( 0.0f ) {
} // Vector3
// -----------------------------------------------------------------------
// Vector3()
// Constructor
inline Vector3::Vector3( float x, float y, float z ) :
m_fx( x ),
m_fy( y ),
m_fz( z ) {
} // Vector3
// -----------------------------------------------------------------------
// Vector3()
// Constructor
inline Vector3::Vector3( float *pfv ) {
m_fx = pfv[0];
m_fy = pfv[1];
m_fz = pfv[2];
} // Vector3
// -----------------------------------------------------------------------
// operator+()
// Unary - Operator:
inline Vector3 Vector3::operator+() const {
return *this;
} // operator+
// -----------------------------------------------------------------------
// operator+()
// Binary - Add Two Vectors Together
inline Vector3 Vector3::operator+( const Vector3 &v3 ) const {
return Vector3( m_fx + v3.m_fx,
m_fy + v3.m_fy,
m_fz + v3.m_fz );
} // operator+
// -----------------------------------------------------------------------
// operator+=()
// Add Two Vectors Together
inline Vector3 &Vector3::operator+=( const Vector3 &v3 ) {
m_fx += v3.m_fx;
m_fy += v3.m_fy;
m_fz += v3.m_fz;
return *this;
} // operator+=
// -----------------------------------------------------------------------
// operator-()
// Unary - Operator: Negate Each Value
inline Vector3 Vector3::operator-() const {
return Vector3( -m_fx, -m_fy, -m_fz );
} // operator-
// -----------------------------------------------------------------------
// operator-()
// Binary - Take This Vector And Subtract Another Vector From It
inline Vector3 Vector3::operator-( const Vector3 &v3 ) const {
return Vector3( m_fx - v3.m_fx,
m_fy - v3.m_fy,
m_fz - v3.m_fz );
} // operator-
// -----------------------------------------------------------------------
// operator-=()
// Subtract Two Vectors From Each Other
inline Vector3 &Vector3::operator-=( const Vector3 &v3 ) {
m_fx -= v3.m_fx;
m_fy -= v3.m_fy;
m_fz -= v3.m_fz;
return *this;
} // operator-=
// -----------------------------------------------------------------------
// operator*()
// Post Multiple Vector By A Scalar
inline Vector3 Vector3::operator*( const float &fValue ) const {
return Vector3( m_fx*fValue, m_fy*fValue, m_fz*fValue );
} // operator*
// -----------------------------------------------------------------------
// operator*=()
// Multiply This Vector By A Scalar
inline Vector3& Vector3::operator*=( const float &fValue ) {
m_fx *= fValue;
m_fy *= fValue;
m_fz *= fValue;
return *this;
} // operator*=
// -----------------------------------------------------------------------
// operator/()
// Post Divide Vector By A Scalar
inline Vector3 Vector3::operator/( const float &fValue ) const {
Vector3 v3;
if ( Math::isZero( fValue ) ) {
v3.m_fx = 0.0f;
v3.m_fy = 0.0f;
v3.m_fz = 0.0f;
} else {
float fValue_Inv = 1/fValue;
v3.m_fx = v3.m_fx * fValue_Inv;
v3.m_fy = v3.m_fy * fValue_Inv;
v3.m_fz = v3.m_fz * fValue_Inv;
}
return v3;
} // operator/
// -----------------------------------------------------------------------
// operator/=()
// Divide This Vector By A Scalar
inline Vector3& Vector3::operator/=( const float &fValue ) {
if ( Math::isZero( fValue ) ) {
m_fx = 0.0f;
m_fy = 0.0f;
m_fz = 0.0f;
} else {
float fValue_Inv = 1/fValue;
m_fx *= fValue_Inv;
m_fy *= fValue_Inv;
m_fy *= fValue_Inv;
}
return *this;
} // operator/=
// -----------------------------------------------------------------------
// divideByVector()
// Division Is Performed By A Vector Component Basis And Returns A Scalar
// With (x*V1) = V2 since (x*V1) = (x*V1i, x*V1j, x*V1k) = V2(i,j,k)
// Then As long as the this vector does not have a 0 component
// We only need to perform the division on the first element of this vector
// where x = V2i / V1i. No need to perform division on j or k.
inline float Vector3::divideByVector( const Vector3& v ) {
if ( Math::isZero( v.m_fx ) ||
Math::isZero( v.m_fy ) ||
Math::izZero( v.m_fz ) ) {
throw( std::string( "Divide By 0" ) );
}
float val = m_fx / v.m_fx;
if ( (val == (m_fy / v.m_fy)) &&
(val == (m_fz / v.m_fz)) ) {
return val;
}
} // divideByVector
// -----------------------------------------------------------------------
// rotateX()
// Rotate This Vector About The X Axis
inline Vector3 Vector3::rotateX( float fRadians ) {
Vector3 v3;
v3.m_fx = m_fx;
v3.m_fy = m_fy*cos( fRadians ) - m_fz*sin( fRadians );
v3.m_fz = m_fy*sin( fRadians ) + m_fz*cos( fRadians );
return v3;
} // rotateX
// -----------------------------------------------------------------------
// rotateY()
// Rotate This Vector About The Y Axis
inline Vector3 Vector3::rotateY( float fRadians ) {
Vector3 v3;
v3.m_fx = m_fx*cos( fRadians ) + m_fz*sin( fRadians );
v3.m_fy = m_fy;
v3.m_fz = -m_fx*sin( fRadians ) + m_fz*cos( fRadians );
return v3;
} // rotateY
// -----------------------------------------------------------------------
// rotateZ()
// Rotate This Vector About The Z Axis
inline Vector3 Vector3::rotateZ( float fRadians ) {
Vector3 v3;
v3.m_fx = m_fx*cos( fRadians ) - m_fy*sin( fRadians );
v3.m_fy = m_fx*sin( fRadians ) + m_fy*cos( fRadians );
v3.m_fz = m_fz;
return v3;
} // rotateZ
// -----------------------------------------------------------------------
// setPerpendicularXY()
// Make This Vector Perp To Vector3
inline void Vector3::setPerpendicularXY( Vector3 v3 ) {
m_fx = -v3.m_fy;
m_fy = v3.m_fx;
m_fz = v3.m_fz;
} // setPerpendicularXY
// -----------------------------------------------------------------------
// setPerpendicularXZ()
// Make This Vector Perp To Vector3
inline void Vector3::setPerpendicularXZ( Vector3 v3 ) {
m_fx = -v3.m_fz;
m_fy = v3.m_fy;
m_fz = v3.m_fx;
} // setPerpendicularXZ
// -----------------------------------------------------------------------
// setPerpendicularYX()
// Make This Vector Perp To Vector3
inline void Vector3::setPerpendicularYZ( Vector3 v3 ) {
m_fx = v3.m_fx;
m_fy = -v3.m_fz;
m_fz = v3.m_fy;
} // setPerpendicularYZ
// -----------------------------------------------------------------------
// cross()
// Get The Cross Product Of Two Vectors
inline Vector3 Vector3::cross( const Vector3 v3 ) const {
return Vector3( m_fy*v3.m_fz - m_fz*v3.m_fy,
v3.m_fx*m_fz - m_fx*v3.m_fz,
m_fx*v3.m_fy - m_fy*v3.m_fx );
} // cross
// -----------------------------------------------------------------------
// dot()
// Return The Dot Product Between This Vector And Another One
inline float Vector3::dot( const Vector3 v3 ) const {
return ( m_fx * v3.m_fx +
m_fy * v3.m_fy +
m_fz * v3.m_fz );
} // dot
// -----------------------------------------------------------------------
// normalize()
// Make The Length Of This Vector Equal To One
inline void Vector3::normalize() {
float fMag;
fMag = sqrt( m_fx*m_fx + m_fy*m_fy + m_fz*m_fz );
if ( fMag <= Math::ZERO ) {
m_fx = 0.0f;
m_fy = 0.0f;
m_fz = 0.0f;
return;
}
fMag = 1/fMag;
m_fx *= fMag;
m_fy *= fMag;
m_fz *= fMag;
} // normalize
// -----------------------------------------------------------------------
// isZero()
// Return True if Vector Is (0,0,0)
inline bool Vector3::isZero() const {
if ( Math::isZero( m_fx ) && Math::isZero( m_fy) && Math::isZero( m_fz ) ) {
return true;
} else {
return false;
}
} // isZero
// -----------------------------------------------------------------------
// zero()
// Set The Value To (0,0,0)
inline void Vector3::zero() {
m_fx = 0.0f;
m_fy = 0.0f;
m_fz = 0.0f;
} // Zero
// -----------------------------------------------------------------------
// getCosAngle()
// Returns The cos(Angle) Value Between This Vector And Vector V. This
// Is Less Expensive Than Using GetAngle
inline float Vector3::getCosAngle( const Vector3 &v3, const bool bNormalized ) {
// a . b = |a||b|cos(angle)
// -> cos-1((a.b)/(|a||b|))
// Make Sure We Do Not Divide By Zero
float fMagA = length();
if ( fMagA <= Math::ZERO ) {
// This (A) Is An Invalid Vector
return 0;
}
float fValue = 0;
if ( bNormalized ) {
// v3 Is Already Normalized
fValue = dot(v3)/fMagA;
}
else {
float fMagB = v3.length();
if ( fMagB <= Math::ZERO) {
// B Is An Invalid Vector
return 0;
}
fValue = dot(v3)/(fMagA*fMagB);
}
// Correct Value Due To Rounding Problem
Math::constrain( -1.0f, 1.0f, fValue );
return fValue;
} // getCosAngle
// -----------------------------------------------------------------------
// getAngle()
// Returns The Angle Between This Vector And Vector V in Radians.
// This Is More Expensive Than Using GetCosAngle
inline float Vector3::getAngle( const Vector3 &v3, const bool bNormalized, bool bRadians ) {
// a . b = |a||b|cos(angle)
// -> cos-1((a.b)/(|a||b|))
if ( bRadians ) {
return acos( this->getCosAngle( v3 ) );
}
else {
// Convert To Degrees
return Math::radian2Degree( acos( getCosAngle( v3, bNormalized ) ) );
}
} // GetAngle
// -----------------------------------------------------------------------
// length()
// Return The Length Of This Vector
inline float Vector3::length() const {
return sqrtf( m_fx * m_fx +
m_fy * m_fy +
m_fz * m_fz );
} // length
// -----------------------------------------------------------------------
// length2()
// Return The Length Of This Vector
inline float Vector3::length2() const {
return ( m_fx * m_fx +
m_fy * m_fy +
m_fz * m_fz );
} // length2
#endif // VECTOR3_H
<强> Vector3.cpp 强>
#include "stdafx.h"
#include "Vector3.h"
// -----------------------------------------------------------------------
// ~Vector3()
// Destructor
Vector3::~Vector3() {
} // ~Vector3
如果您注意到我的Vector3类中有一堆操作符和常用的函数,可以应用于3个组件的向量。现在,除法运算符返回一个vector3,并用标量除以每个分量。由于这个原因,我还包括了一个朋友操作符/和一个函数调用divideByVector。他们将做同样的操作。在代码中使用它们就像这样简单。
#include "stdafx.h" // string isostream etc.
#include "Vector3.h"
int main() {
Vector3 v1 ( 4.0f, 4.0f, 4.0f );
Vector3 v2 ( 2.0f, 2.0f, 2.0f );
float value = v1.divideByVector( v2 );
std::cout << value << std::endl;
value = v2.divideByVector( v1 );
std::cout << value << std::endl;
std::cout << v1 / v2 << std::endl;
std::cout << v2 / v1 << std::endl;
v1.m_fx = 0;
v2.m_fx = 0;
std::cout << v1.divideByVector( v2 ) << std::endl;
std::cout << v2.divideByVector( v1 ) << std::endl;
std::cout << v1 / v2 << std::endl;
std::cout << v2 / v1 << std::endl;
std::cout << "\nPress any key to quit.\n" << std::endl;
_getch();
return 0;
} // main
您还可以尝试向量,其中一个组件的每个组件不是另一个组件的多个组合,例如:v1( 15.0f, 25.0f, 30.0f ) & v2( 3.0f, 5.0f, 7.0f)
如果v2's k component
现在v2's k component was 6.0f
,则会因5
而失败返回的结果值应为0.2
,如果您反转除法,则应为-nan(ind)
。现在使用我的编译器(VS2015)如果这些值不是常见的倍数打印的消息给我的屏幕是:
try { ... } catch( ... ) { }
如果将0作为值传递并尝试除以它,则调试器将抛出未处理的异常。通常,这将作为消息抛出并捕获到rand
块中。但是我没有我的Logger和我的ExceptionHandler类可用于此演示。另请注意,由于我现在使用srand
库,因此我不再使用<random>
或willRotateToInterfaceOrientation:
,因此旧版库中的某些功能已弃用或已修订。