Math.Sin给我怪异的价值观

时间:2019-03-11 21:18:35

标签: c# algorithm xamarin math

我正在尝试创建一个径向FAB菜单,并定义所有圆的位置,我有一个算法在理论上可以正常工作,但是当我实际运行它时,Y值给了我一些奇怪的东西。 。我会尽快发布代码

请注意,除非您需要参考值的含义,否则这部分并不是很重要

    public class FABContainer : AbsoluteLayout
    {
        public static int NUMBER_FOR_RING = 1;
        public static double ANGLE_INCREMENT = 360.0 / ((double)NUMBER_FOR_RING);
        public static double CENTER_RADIUS = 100;
        public static double WIDTH_MOD = 0.9;
        public FABContainer()
        {
            this.BackgroundColor = Color.Transparent;
            FAB fab = new FAB();
            List<InternalFAB> internals = new List<InternalFAB>();
            internals.Add(new InternalFAB(this, internals.Count)
            {
            });
            this.Children.Add(fab);
            foreach(InternalFAB f in internals) { this.Children.Add(f); };
        }
    }
    public partial class FAB : SuaveControls.Views.FloatingActionButton
    {
        public FAB()
        {
            this.HeightRequest = FABContainer.CENTER_RADIUS;
            this.WidthRequest = FABContainer.CENTER_RADIUS * FABContainer.WIDTH_MOD;
            Debug.WriteLine($"CREATING NEW CENTER WITH W: {this.WidthRequest} H: {this.HeightRequest}");
                this.Image = "Edit_Icon.png";
            this.BackgroundColor = Color.Transparent;
            this.CornerRadius = (int)this.HeightRequest;
        }
    }
    internal class InternalFAB : SuaveControls.Views.FloatingActionButton
    {
        public static double DIST = 5;
        public EventHandler OnClicked;
        public static double radius = 80;
        public InternalFAB(FABContainer container, int count)
        {
            this.HeightRequest = (radius);
            this.WidthRequest = (radius * FABContainer.WIDTH_MOD * 0.95);
            this.BackgroundColor = Color.Transparent;
            int index = count + 1;
            double AngleDistortion = ((double)index) * FABContainer.ANGLE_INCREMENT;

            double xpos = (DIST + this.WidthRequest) * (Math.Cos((Math.PI / 180.0) * AngleDistortion));
            double ypos = (DIST + this.HeightRequest) * (Math.Sin((Math.PI / 180.0) *AngleDistortion));

            Debug.WriteLine($"CREATING NEW INTERNAL AT: {xpos},{ypos} from distortion {AngleDistortion}");

            this.TranslationX = xpos;
            this.TranslationY = ypos;
        }
    }

没关系,但这是使用Xamarin。本质上,实际上很重要并给我带来问题的部分是以下部分:

double AngleDistortion = ((double)index) * FABContainer.ANGLE_INCREMENT;

double xpos = (DIST + this.WidthRequest) * (Math.Cos((Math.PI / 180.0) * AngleDistortion));
double ypos = (DIST + this.HeightRequest) * (Math.Sin((Math.PI / 180.0) *AngleDistortion));

Debug.WriteLine($"CREATING NEW INTERNAL AT: {xpos},{ypos} from distortion {AngleDistortion}");

无论出于何种原因,Y值都将返回为 -2.08183080149804E-14 ,而不是“完美”情况下应返回的0。我遍历了我的代码,以试图发现错误无济于事。

如果您需要有关我的代码的更多说明,我会立即告诉您。

1 个答案:

答案 0 :(得分:0)

乘以85对这个问题并不重要,因此我将其放在一边,而仅研究(有效)Math.Sin(Math.PI * 2)。其结果是在我的计算机上-2.44921270764475E-16

当然,浮点算术不是精确的,但结果并不是胡扯。这里发生的是,在x = 2pi附近,sin(x)≈x-2pi。但是,Math.Sin(Math.PI * 2)不会精确评估2pi的正弦,它不能,2pi是先验的,绝对不能表示为浮点数。正弦输入已经稍微“关闭”,并且具有一些值v=fl(2pi),其中fl将值四舍五入到最接近的可表示浮点数。然后sin(v) ≈ v - 2pi,因为v接近2pi。

因此Math.Sin(Math.PI * 2)的结果应大致代表我们作为参数传递的2 pi与 real 2 pi的距离。 Math.PI * 2在我的机器上的准确值为6.28318530717958623199592693708837032318115234375,即-2.4492935982947063544521318645500 ...×10 ^ -16距 real 2 pi,这非常接近到先前的-2.44921270764475E-16值。它不完全在那儿,但足够接近以表明它不仅仅是任意的。