1. C# / Говнокод #29152

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    // https://github.com/dotnet/runtime/issues/117233#issuecomment-3028066225
    
    // Issue: Math.Pow relies directly on the OS pow implementation
    
    // Location: [src/coreclr/classlibnative/float/floatdouble.cpp lines 232‑236] and [src/coreclr/classlibnative/float/floatsingle.cpp lines 207‑211]
    
    // COMDouble::Pow and COMSingle::Pow simply call pow/powf from the C runtime. On Windows 11 Insider Preview (build 27881.1000),
    // these functions can return incorrect results (e.g., Math.Pow(-1, 2) giving -1). The JIT also uses these functions for constant folding, causing
    // wrong constants to be embedded at compile time.
    
    // Suggested Fix: Introduce a managed fallback in COMDouble::Pow/COMSingle::Pow that handles negative bases with integral exponents, bypassing the faulty system call.
    
    //A simple approach:
    
    FCIMPL2_VV(double, COMDouble::Pow, double x, double y)
    {
        FCALL_CONTRACT;
    
        if ((x < 0.0) && (y == floor(y)))
        {
            double absResult = pow(-x, y);
            return fmod(fabs(y), 2.0) == 1.0 ? -absResult : absResult;
        }
    
        return pow(x, y);
    }
    
    // Suggested Implementation:
    
    // Add the following code to src/coreclr/classlibnative/float/floatdouble.cpp below line 234 before the return pow:
    
    if ((x < 0.0) && (y == floor(y)))
    {
        double result = pow(-x, y);
    
        if (fmod(fabs(y), 2.0) != 0.0)
        {
            result = -result;
        }
    
        return result;
    }
    
    // Add the following code to src/coreclr/classlibnative/float/floatsingle.cpp below line 209 before the return powf:
    
    if ((x < 0.0f) && (y == floorf(y)))
    {
        float result = powf(-x, y);
    
        if (fmodf(fabsf(y), 2.0f) != 0.0f)
        {
            result = -result;
        }
    
        return result;
    }
    
    // Add the following code to src/libraries/System.Runtime/tests/System.Runtime.Extensions.Tests/System/Math.cs below line 1124:
    
    [Fact]
    public static void Pow_NegativeBaseEvenExponent_ReturnsPositive()
    {
        Assert.Equal(1.0, Math.Pow(-1, 2));
        Assert.Equal(16.0, Math.Pow(-2, 4));
    }

    Вот к чему плавучий петух приводит!

    Запостил: j123123, 04 Июля 2025

    Комментарии (17) RSS

    • В шарпе еще есть какая-то функция возведения для комплексных чисел, можно наверное ее использовать, брать действительную часть
      https://learn.microsoft.com/uk-ua/dotnet/api/system.numerics.complex.pow?view=net-10.0
      public static System.Numerics.Complex Pow(System.Numerics.Complex value, double power);

      Только вот какого хрена там первый аргумент комплесный, второй это обычный дабл? У меня в Си у "cpow" оба аргумента комплексные:
      double complex cpow(double complex x, double complex z);

      Именно поэтому я за Си
      Ответить
      • > double complex x

        Это как? Встроенный в язык тип что ли?
        Ответить
        • https://en.cppreference.com/w/c/language/arithmetic_types.html#Complex_floating_types


          Там и Imaginary есть
          Ответить
          • Получается, что теперь нельзя заглавную I использовать в качестве имени переменной или макроса?
            Ответить
            • Если у тебя есть #include <complex.h> то нельзя.
              Ответить
              • Всё, вижу:

                #ifdef __GNUC__
                #define	_Complex_I	((float _Complex)1.0i)
                #endif
                
                #define	complex		_Complex
                #define	I		_Complex_I


                Т. е. на уровне языка I не зашкварена, есть просто суффикс для литералов: 1.23i. Значит, никакой необходимости в #define I нету.
                Ответить
              • --место--для-шутки-про-min-max-и-windows.h--
                Ответить
                • Windows SDK — это ад. Некоторые хедеры ломают определения из хедеров самого компилятора, так что результат компиляции может зависеть от порядка #include.

                  Это авгиевы конюшни.
                  Ответить
        • Это кто-то забыл, что макросня должна писаться с болшой буквы
          Ответить
          • Макрос с большой буквы
            Слово "макрос" пишется с большой буквы
            Ответить
          • Хорошо, тут макрос написали с маленькой. Но макрос не волшебная палочка, он разворачивается во встроенный тип _Complex.
            Ответить
            • А можно для тех, кто в кулинарном техникуме учился: нахуя нужны комплексные числа вообще? В чем поинт?
              Ответить
              • Помнишь, как в начальной школе решали задачи, избегая отрицательных чисел и дробных чисел? Получалось, но в голове приходилось прокручивать кучу «ифов».

                Так вот с комплексными что-то похожее: они позволяют некоторые задачи решать единой формулой без ветвления.
                Ответить
    • >On Windows 11 Insider Preview (build 27881.1000),
      // these functions can return incorrect results

      .net: write once, test everywhere. Сука.
      Ответить
    • Это очень смешно))

      Это как если бы оператор "+" у двух четрехбайтовых целых зависел от версии либси
      Ответить
      • g: pentium fdiv bug

        А ты над библиотекой смеёшься...

        К слову, в первая партия 80386 оказалась бракованной: на ней целочисленное деление 32-битных чисел (в смысле не когда 32 бита в DX+AX, а когда делитель 32-битный) иногда давало неправильный результат. Эту партию процессоров промаркировали: «Только для 16-битных приложений!» Вторая партия была уже исправленной.

        А в «Пентиуме» ничего исправлять не стали, поэтому в библиотеках пришлось городить «fdiv workaround».
        Ответить
    • Я в своё время писал свою функцию для возведения вещественных чисел в дробную степень. Показатель степени через разложение в цепную дробь преобразовывал в обыкновенную дробь (с заданной точностью). Далее при отрицательном основании рассматривал варианты:

      1. Если знаменатель показателя степени чётный, посылал нахуй, ибо результат в этом случае должен быть чисто мнимым, а я писал для вещественных чисел.

      2. Если знаменатель показателя степени нечётный, то знак результата выбирал в зависимости от чётности числителя показателя степени.

      При положительном основании, естественно, проблем нет.

      То есть я доопределил операцию возведения в степень до предсказуемого результата, выбрав при дробном показателе самый очевидный корень.
      Ответить

    Добавить комментарий