小型基本乌龟 MoveTo 错误 "Value was either too large or too small for a Decimal."
Small basic turtle MoveTo error "Value was either too large or too small for a Decimal."
这段代码似乎抛出了异常"Value was either too large or too small for a Decimal."
以某种方式更改变量 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 版本相同。
问题是 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
}
这段代码似乎抛出了异常"Value was either too large or too small for a Decimal."
以某种方式更改变量 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 版本相同。
问题是 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
}