C brainfuck

bleyman

Есть такой кот:

double f = atof(get_field("some_field";
// ...
f = -f;
// ...
if (f < 0) f = -f;
sprintf(s, "%f", f);
set_field("converted_field", s);
if (s[0] == '-')
{
   set_field("critically_important_field", "XX");
}

В какой-то момент клиент открывает критикал приорити баг: критикалли_импортант_филд перестал заполняться.
Прикольно, правда?

apl13

$ cat test.c && gcc test.c && echo 'Get ready!' && ./a.out 
#include <stdio.h>

int main {
double a = 0;
a = -a;
printf("%f\n", a);
return 0;
}
Get ready!
-0.000000

Maurog

Прикольно, правда?
double вообще неприкольный тип :grin: и это не только сей касается

apl13

Даже так:
$ cat test.c && gcc test.c && echo 'Get ready!' && ./a.out 
#include <stdio.h>

int main {
double a = 0;
a = -a;
printf("%f, %d\n", a, a < 0);
return 0;
}
Get ready!
-0.000000, 0

Serab

вот именно, без этого ок :)

apl13

Меня вот это сильнее всего печалит в дабле: даже если он число, его еще так просто не сравнишь.

bleyman

Ага, именно так.
Что меня наиболее в этом всём поражает, это что одной из миллионов обезьян удалось написать код, опирающийся на эту фичу даблов.

ava3443

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

bleyman

Ну, ни в С, ни в С++ нет класса decimal, так что выбора особо нет тоже.
А так — почему бы и не использовать даблы для этого? Как бы что бы там себе ни думали люди, впервые столкнувшиеся с особенностями арифметики над ними и испугавшиеся до усрачки, там всё чотко определено, и обычно чотко же и работает. Особенно если такой херни, с определением положительности через первый символ результата sprintf, не писать. Алсо, 56 бит мантиссы вполне достаточно для всего.

slonishka

В gcc, кстати, есть какие-то нестандартные типы такого плана, может пригодится кому эта инфа.
Как работают - черт их знает, не пользовался никогда. Ну должны шустрые быть...
http://gcc.gnu.org/onlinedocs/gcc/Fixed_002dPoint.html

Papazyan

С ограниченными после запятой типами есть один косяк - они теряют точность при умножении/делении на что-нибудь. См. хитрожопых граждан, которые отправляли эти хвосты себе на счет.

ava3443

C++ класс для currency на основе 64-bit инта делается довольно легко, и потом работает без серьёзных изменений десяток лет.
почему бы и не использовать даблы для этого? Как бы что бы там себе ни думали люди, впервые столкнувшиеся с особенностями арифметики над ними и испугавшиеся до усрачки, там всё чотко определено, и обычно чотко же и работает.
Вот именно, чотко определено что это m/2^n, что не позволяет точно представить decimal число, которое m/(2^n*5^n). Если на точность округлений пофигу, то можно и даблы. Но я пока не видел расчётной системы, где было бы пофигу. Например, как только требуется вычислять проценты, это становится критичным. Your mileage may vary :)

ava3443

вот собственно про требуемое округление: http://en.wikipedia.org/wiki/Rounding#Rounding_to_a_specifie...
даблами этого не сделать.

apl13

даблами этого не сделать.
1. Divide x by m, let the result be y;
2. Round y to an integer value, call it q;
3. Multiply q by m to obtain the rounded value z.
:confused:

bleyman

> Если на точность округлений пофигу
Ну, там всегда же в конце концов дабл превращается принтфом в строку с заданным количеством позиций до и после запятой. Принтф округляет их вменяемо.
> Но я пока не видел расчётной системы, где было бы пофигу.
Я пока не видел расчётной системы, где использовалось что-нибудь другое кроме даблов для вычисления процентов =(. С другой стороны, я ни разу не видел баг-репорта где дебит не сходился бы с кредитом из-за этого =)

xronik111

Если уж на то пошло:
Decimal floating-point arithmetic based on draft ISO/IEC TR 24732, N1241, is now supported as a GCC extension to C for targets i[34567]86-*-linux-gnu, powerpc*-*-linux-gnu, s390*-ibm-linux-gnu, and x86_64-*-linux-gnu. The feature introduces new data types _Decimal32, _Decimal64, and _Decimal128 with constant suffixes DF, DD, and DL.
Начиная с 4.3.
Warning: насколько я помню, это люди из IBM делали, поэтому если это не работает где-то снаружи PowerPC и S390, может никого не взволновать.

ViperTM

а чего удивительного?
то, что дабл определен с какой-то точностью - думаю всем понятно. Как printf делает вывод дабла я не знаю, но очевидно, что не через " if (a < 0.0) ". Собственно, 0=-0, это и продемонстрировал пример, нет? Или тебя смущает знак '-' перед нулем? =)
Единственное что доставляет — писать fabs (x-y) < 1e-14 всякий раз, когда хочется проверить на равенство (ну или нестрогое неравенство без fabs но оно же так специально и делается. Если хочется, чтобы за вас все делал компилятор, пишите на Java или поделках майкрософта, в чем проблема?

Serab

Если хочется, чтобы за вас все делал компилятор, пишите на Java или поделках майкрософта, в чем проблема?
а что, он даблы с точностью до eps сравнивает?

apl13

Ты мне, что ли? Меня тут ничего не смущает. Смущает клиента тредстартера, перешли ему, пожалуйста, свое сообщение.
А вообще обычный тред про индийский код, лол, сравнение на ненулевость f через проверку знака, вычисление в лоб модуля и распечатывание в строку, бва-ха-ха, и все ради `if(f) set_field("critically_important_field", "XX");'.
А вы говорите "toString.length < 5"...

bleyman

Decimal floating-point arithmetic based on draft ISO/IEC TR 24732, N1241, is now supported as a GCC extension
Начиная с 4.3.
Ну, мне вообще-то нужно было при помощи 2.95 под 5.7 солярис компилить =) В процессе узнал много нового про кроссплатформенность на примере функций signbit и copysign (в С++ их нет).
@Dizzy: не, не только про индусов, на самом деле. Мне показалось любопытным, что абстракция "отрицательный ноль" с одной стороны вроде прочная, а с другой — течёт через принтф (которым мне, кстати, и пришлось заменить copysign/signbit, дабы ничего не поломать в других местах кода случайно).
Оставить комментарий
Имя или ник:
Комментарий: