1

此代码似乎引发异常“值对于小数而言太大或太小”。

以某种方式更改变量 y1、y2、x 会消除错误。例如,y2 从 41 到 38。

我怎样才能解决这个问题?

Turtle.Speed = 10
x = 10
y1 = 42
y2 = 41
Turtle.Angle = 180
Turtle.MoveTo(x, y2)
Turtle.MoveTo(x, y1)

错误跟踪:

in System.Decimal..ctor(Double value)
in System.Decimal.op_Explicit(Double value)
in Microsoft.SmallBasic.Library.Primitive.op_Implicit(Double value)
in Microsoft.SmallBasic.Library.Turtle.MoveTo(Primitive x, Primitive y)
in _SmallBasicProgram._Main()

在 1.0 和 1.2 版本中相同。

4

1 回答 1

1

问题是 SmallBasic(1.2 版)Primitive-from-double 实现存在缺陷。下面是如何将 double 转换为 Primitive。

new Primitive((Decimal) primitiveDouble);

然而,这是一个不安全的操作,因为并非所有的双精度值都可以(精确)表示。在这些情况下,转换为 Decimal 将引发异常。

这是在 C# 中重现此类异常的一种简单方法:

double x = double.MinValue; // [smallest] denormalized value
decimal f = (decimal)x;

这发生在MoveTo(x,y)执行三角数学以将MoveTo转换为Turn+Move组合的操作中。对于某些输入(以及海龟所在的位置),这将导致无法 [安全地] 转换为十进制值的双精度数。

显式使用Turn+将避免有问题的数学,因此应该避免问题 - 至少在这种特殊情况下。Move

作为参考,这里是MoveTo的反编译源:

/// <summary>
/// Turns and moves the turtle to the specified location.  If the pen is down, it will draw a line as it moves.
/// </summary>
/// <param name="x">The x co-ordinate of the destination point.</param>
/// <param name="y">The y co-ordinate of the destination point.</param>
public static void MoveTo(Primitive x, Primitive y)
{
  double d = (double) ((x - Turtle.X) * (x - Turtle.X) + (y - Turtle.Y) * (y - Turtle.Y));
  if (d == 0.0)
    return;
  double num1 = System.Math.Sqrt(d);
  double num2 = System.Math.Acos((double) (Turtle.Y - y) / num1) * 180.0 / System.Math.PI;
  if ((bool) (x < Turtle.X))
    num2 = 360.0 - num2;
  double num3 = num2 - (double) ((int) Turtle.Angle % 360);
  if (num3 > 180.0)
    num3 -= 360.0;
  Turtle.Turn((Primitive) num3); // goes boom here..
  Turtle.Move((Primitive) num1); // ..or here
}
于 2018-10-07T22:39:22.300 回答