首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >轴承(角)类定义良好的数学运算

轴承(角)类定义良好的数学运算
EN

Software Engineering用户
提问于 2015-02-04 13:25:26
回答 1查看 801关注 0票数 3

我写了一个类来表示方位(角度与航海主题,和一个具体的正常化范围)。在程序中,有必要对它们执行一些数学操作,因此我重载了+、-、*和/运算符(这是C++中的)。

我的问题是:什么样的运算符在数学上定义得很好?或者更具体地说,在下面的代码中,是否有任何我不应该定义的运算符,以及是否有任何未定义的运算符是我应该定义的?

代码语言:javascript
复制
constexpr inline Bearing operator+(Bearing lhs, Bearing rhs) noexcept
{
    return Bearing::deg(lhs.getInDegrees() + rhs.getInDegrees());
}

constexpr inline Bearing operator-(Bearing lhs, Bearing rhs) noexcept
{
    return Bearing::deg(lhs.getInDegrees() - rhs.getInDegrees());
}

template <
    typename T,
    typename = EnableIfNumeric<T>
> constexpr inline Bearing operator*(Bearing lhs, T rhs) noexcept
{
    return Bearing::deg(lhs.getInDegrees() * static_cast<Bearing::ValueType>(rhs));
}

template <
    typename T,
    typename = EnableIfNumeric<T>
> constexpr inline Bearing operator*(T lhs, Bearing rhs) noexcept
{
    return Bearing::deg(static_cast<Bearing::ValueType>(lhs) * rhs.getInDegrees());
}


template <
    typename T,
    typename = EnableIfNumeric<T>
> constexpr inline Bearing operator/(Bearing lhs, T rhs) noexcept
{
    return Bearing::deg(lhs.getInDegrees() / static_cast<Bearing::ValueType>(rhs));
}

template <
    typename T,
    typename = EnableIfNumeric<T>
> constexpr inline Bearing operator/(T lhs, Bearing rhs) noexcept; // Intentionally not defined

constexpr inline Bearing::ValueType operator/(Bearing lhs, Bearing rhs) noexcept
{
    return lhs.getInDegrees() / rhs.getInDegrees();
}

// Bearing has value semantics
constexpr inline Bearing operator+=(Bearing lhs, Bearing rhs) noexcept; // Intentionally not defined
constexpr inline Bearing operator-=(Bearing lhs, Bearing rhs) noexcept; // Intentionally not defined
constexpr inline Bearing operator*=(Bearing lhs, Bearing rhs) noexcept; // Intentionally not defined
constexpr inline Bearing operator/=(Bearing lhs, Bearing rhs) noexcept; // Intentionally not defined


constexpr inline bool operator==(Bearing lhs, Bearing rhs) noexcept
{
    return lhs.getInDegrees() == rhs.getInDegrees();
}

constexpr inline bool operator!=(Bearing lhs, Bearing rhs) noexcept
{
    return !(lhs == rhs);
}

用词:

  • (在上述代码中未显示)轴承实例必须由静态方法创建,静态方法包含::deg或轴承::rad,因此在初始化时单元是显式的。
  • 轴承只能加到其他轴承上或从其他轴承中减去。
  • 轴承只能乘以数值类型(其他轴承除外)。
  • 轴承只能分为数字类型。
  • 数字类型不能用轴承来划分。
  • 轴承可除以其他轴承,产生浮点值。
  • 轴承有相等的比较运算符,但没有不等式比较运算符(因为角环绕,如果a和b是轴承,则a
  • (请注意,有一些成员函数可以确定一个轴承与另一个轴承之间的绝对距离和顺时针/逆时针距离,因此,无论您对不等式比较操作符做什么,都应该是可能的)

注意,所谓“正规化”,我指的是环绕角度,使它们始终在[0,360)或[-180,180]范围内,并且该操作仅在客户请求时执行,而不是在每次操作之后执行。

我认为这个问题很适合程序员,但是如果有几个人认为它更适合于代码评审,那么我会考虑把它移到那里。

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2015-02-04 13:55:50

这取决于“数学上定义良好”的含义。您的所有函数都在有唯一定义的意义上得到了很好的定义。然而,乘法和除法是有问题的,因为它们不能保证

代码语言:javascript
复制
(b * n) * m == b * (n * m)

nor

代码语言:javascript
复制
(b * n) / m == b * (n / m)

其中b是轴承,n是数字值,这就是您可能期望的。例如,如果b = 45°n = m = 8

代码语言:javascript
复制
(b * n) / m == 360° / 8 == 0° / 8 == 0°

但b* (n / m) == 45°*1 == 45°

(或者使用乘法,设置m = 1/8,它显示的本质是相同的)。

所以,如果你想让这件事变得万无一失,我建议你用调用者给出的间隔(例如,0°到360°或乘法,或者设置为-180°到180°)添加一个从轴承到浮点的转换操作符。乘法和除法只能通过使用这个范围把一个方位转换成一个数字,然后应用这个运算,然后再转换回一个方位。这样就可以消除每一个歧义。

票数 3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/272084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档