Информация об изменениях

Сообщение Re: [StackOverflow] вопросы недели от 01.12.2016 18:11

Изменено 23.08.2025 21:30 netch80

Re: [StackOverflow] вопросы недели
Здравствуйте, Sinix, Вы писали:

S>1. Красивейший гейзенбаг:


Запощу для архива аналог для C.

#include <stdio.h>
#include <ieeefp.h>

volatile float a, b, f1;
int main() {
  fpsetprec(FP_PD);
  a = 0.1f;
  b = 0.2f;
  f1 = a + b;
  printf("%d\n", f1 == (a + b));
  return 0;
}


fpsetprec это для FreeBSD, для других платформ _controlfp и тому подобное. FP_PS ставит точность на single, ответ — 1. FP_PD (double), FP_PE (extended) приводит к ответу 0. Разумеется, компиляция должна быть с использованием FPU (умолчание для 32 бит), на SSE не повторяется. От уровня отладки не зависит, благодаря volatile.

В ассемблере получается

 80485c8:       d9 05 b8 98 04 08       flds   a
 80485ce:       d9 05 c0 98 04 08       flds   b
 80485d4:       de c1                   faddp  %st,%st(1)
 80485d6:       d9 1d bc 98 04 08       fstps  f1
 80485dc:       d9 05 bc 98 04 08       flds   f1
 80485e2:       d9 05 b8 98 04 08       flds   a
 80485e8:       d9 05 c0 98 04 08       flds   b
 80485ee:       de c1                   faddp  %st,%st(1)
 80485f0:       da e9                   fucompp


и за счёт сравнения на стеке FPU при более широкой точности — получается данный эффект.

В стандарте C возможность подобного определяется макросом FLT_EVAL_METHOD, но в этих тестах он был равен -1, что значит, что нет определённости на этапе компиляции. Для 64-битного режима с использованием SSE он равен 0.
В дотнете, как я понял, спросить это нет возможности.
floating point
Re: [StackOverflow] вопросы недели
Здравствуйте, Sinix, Вы писали:

S>1. Красивейший гейзенбаг:


Запощу для архива аналог (не в смысле гейзенбага, а воспроизведение ситуации, которая найдена при разборе) для C.

#include <stdio.h>
#include <ieeefp.h>

volatile float a, b, f1;
int main() {
  fpsetprec(FP_PD);
  a = 0.1f;
  b = 0.2f;
  f1 = a + b;
  printf("%d\n", f1 == (a + b));
  return 0;
}


fpsetprec это для FreeBSD, для других платформ _controlfp и тому подобное. FP_PS ставит точность на single, ответ — 1. FP_PD (double), FP_PE (extended) приводит к ответу 0. Разумеется, компиляция должна быть с использованием FPU (умолчание для 32 бит), на SSE не повторяется. От уровня отладки не зависит, благодаря volatile.

В ассемблере получается

 80485c8:       d9 05 b8 98 04 08       flds   a
 80485ce:       d9 05 c0 98 04 08       flds   b
 80485d4:       de c1                   faddp  %st,%st(1)
 80485d6:       d9 1d bc 98 04 08       fstps  f1
 80485dc:       d9 05 bc 98 04 08       flds   f1
 80485e2:       d9 05 b8 98 04 08       flds   a
 80485e8:       d9 05 c0 98 04 08       flds   b
 80485ee:       de c1                   faddp  %st,%st(1)
 80485f0:       da e9                   fucompp


и за счёт сравнения на стеке FPU при более широкой точности — получается данный эффект.

В стандарте C возможность подобного определяется макросом FLT_EVAL_METHOD, но в этих тестах он был равен -1, что значит, что нет определённости на этапе компиляции. Для 64-битного режима с использованием SSE он равен 0.
В дотнете, как я понял, спросить это нет возможности.
floating point