How deterministic is floating point inaccuracy?

后端 未结 10 1442
长发绾君心
长发绾君心 2020-11-27 06:51

I understand that floating point calculations have accuracy issues and there are plenty of questions explaining why. My question is if I run the same calculation twice, can

10条回答
  •  独厮守ぢ
    2020-11-27 07:20

    This is not a full answer to your question, but here is an example demonstrating that double calculations in C# are non-deterministic. I don't know why, but seemingly unrelated code can apparently affect the outcome of a downstream double calculation.

    1. Create a new WPF application in Visual Studio Version 12.0.40629.00 Update 5, and accept all the default options.
    2. Replace the contents of MainWindow.xaml.cs with this:

      using System;
      using System.Windows;
      
      namespace WpfApplication1
      {
          /// 
          /// Interaction logic for MainWindow.xaml
          /// 
          public partial class MainWindow : Window
          {
              public MainWindow()
              {
                  InitializeComponent();
                  Content = FooConverter.Convert(new Point(950, 500), new Point(850, 500));
              }
          }
      
          public static class FooConverter
          {
              public static string Convert(Point curIPJos, Point oppIJPos)
              {
                  var ij = " Insulated Joint";
                  var deltaX = oppIJPos.X - curIPJos.X;
                  var deltaY = oppIJPos.Y - curIPJos.Y;
                  var teta = Math.Atan2(deltaY, deltaX);
                  string result;
                  if (-Math.PI / 4 <= teta && teta <= Math.PI / 4)
                      result = "Left" + ij;
                  else if (Math.PI / 4 < teta && teta <= Math.PI * 3 / 4)
                      result = "Top" + ij;
                  else if (Math.PI * 3 / 4 < teta && teta <= Math.PI || -Math.PI <= teta && teta <= -Math.PI * 3 / 4)
                      result = "Right" + ij;
                  else
                      result = "Bottom" + ij;
                  return result;
              }
          }
      }
      
    3. Set build configuration to "Release" and build, but do not run in Visual Studio.

    4. Double-click the built exe to run it.
    5. Note that the window shows "Bottom Insulated Joint".
    6. Now add this line just before "string result":

      string debug = teta.ToString();
      
    7. Repeat steps 3 and 4.

    8. Note that the window shows "Right Insulated Joint".

    This behavior was confirmed on a colleague's machine. Note that the window consistently shows "Right Insulated Joint" if any of the following are true: the exe is run from within Visual Studio, the exe was built using the Debug configuration, or "Prefer 32-bit" is unchecked in project properties.

    It's quite difficult to figure out what's going on, since any attempt to observe the process appears to change the result.

提交回复
热议问题