Тогда там всего 16 цельночисленных значений. Но тем не менее конечно круто, использовать для промежуточного хранения 16 целых значений переменную с миллиардами возможных значений и обрабатываемую навороченной ресурсоёмкой математикой для плавающей точки, чтобы потом обратно его перевести в 16 значений. И главное, подобные чудеса обычно пишутся для 8-ми битных контроллеров без аппаратной floating point support
Ладно, что-то увлёкся я флудом, здесь и без меня есть кому сказать своё веское слово .
Чтобы сравнить 2 числа 23,56434569 и 33,65497437 умный компилятор может сначала сравнить числа стоящие до запятой и этого окажется достаточно для принятия решения.
Сравнение float в attiny13 c оптимизацией по размеру
avr-gcc 8.2.0
Скрытый текст
Код:int main ( void ) { volatile float var ; var = 123.456 ; return var > 123.455f ? 1 : 0 ; } 0: cd b7 in r28, 0x3d ; 61 2: dd 27 eor r29, r29 4: c4 50 subi r28, 0x04 ; 4 6: cd bf out 0x3d, r28 ; 61 8: 89 e7 ldi r24, 0x79 ; 121 a: 99 ee ldi r25, 0xE9 ; 233 c: a6 ef ldi r26, 0xF6 ; 246 e: b2 e4 ldi r27, 0x42 ; 66 10: 89 83 std Y+1, r24 ; 0x01 12: 9a 83 std Y+2, r25 ; 0x02 14: ab 83 std Y+3, r26 ; 0x03 16: bc 83 std Y+4, r27 ; 0x04 18: 69 81 ldd r22, Y+1 ; 0x01 1a: 7a 81 ldd r23, Y+2 ; 0x02 1c: 8b 81 ldd r24, Y+3 ; 0x03 1e: 9c 81 ldd r25, Y+4 ; 0x04 20: 01 e0 ldi r16, 0x01 ; 1 22: 10 e0 ldi r17, 0x00 ; 0 24: 26 ef ldi r18, 0xF6 ; 246 26: 38 ee ldi r19, 0xE8 ; 232 28: 46 ef ldi r20, 0xF6 ; 246 2a: 52 e4 ldi r21, 0x42 ; 66 2c: 08 d0 rcall .+16 ; 0x3e 2e: 18 16 cp r1, r24 30: 14 f0 brlt .+4 ; 0x36 32: 10 e0 ldi r17, 0x00 ; 0 34: 00 e0 ldi r16, 0x00 ; 0 36: c8 01 movw r24, r16 38: cc 5f subi r28, 0xFC ; 252 3a: cd bf out 0x3d, r28 ; 61 3c: 08 95 ret 3e: 03 d0 rcall .+6 ; 0x46 40: 08 f4 brcc .+2 ; 0x44 42: 8f ef ldi r24, 0xFF ; 255 44: 08 95 ret 46: 99 0f add r25, r25 48: 00 08 sbc r0, r0 4a: 55 0f add r21, r21 4c: aa 0b sbc r26, r26 4e: e0 e8 ldi r30, 0x80 ; 128 50: fe ef ldi r31, 0xFE ; 254 52: 16 16 cp r1, r22 54: 17 06 cpc r1, r23 56: e8 07 cpc r30, r24 58: f9 07 cpc r31, r25 5a: c0 f0 brcs .+48 ; 0x8c 5c: 12 16 cp r1, r18 5e: 13 06 cpc r1, r19 60: e4 07 cpc r30, r20 62: f5 07 cpc r31, r21 64: 98 f0 brcs .+38 ; 0x8c 66: 62 1b sub r22, r18 68: 73 0b sbc r23, r19 6a: 84 0b sbc r24, r20 6c: 95 0b sbc r25, r21 6e: 39 f4 brne .+14 ; 0x7e 70: 0a 26 eor r0, r26 72: 61 f0 breq .+24 ; 0x8c 74: 23 2b or r18, r19 76: 24 2b or r18, r20 78: 25 2b or r18, r21 7a: 21 f4 brne .+8 ; 0x84 7c: 08 95 ret 7e: 0a 26 eor r0, r26 80: 09 f4 brne .+2 ; 0x84 82: a1 40 sbci r26, 0x01 ; 1 84: a6 95 lsr r26 86: 8f ef ldi r24, 0xFF ; 255 88: 81 1d adc r24, r1 8a: 81 1d adc r24, r1 8c: 08 95 ret
Дьявол в деталях: Компилятор не может заранее знать, какие диапазоны придется сравнивать (если оба операнда константы, то задача вырождается в слишком простую для компилятора). Он использует код библиотеки, которая затем прилинкуется к общему. Библиотека, да, должна начать с правильного конца, чтобы по-быстрому вернуть результат и успеть покурить.
Что касается инструкций, то в большинстве случаев используется gcc, проще сравнивать.
P.S. Глянул в тех-референсе блок плавающей точки одинарной точности для F4 (недавно ковырял компиляцию), в нем есть инструкция сравнения двух fpu-регистров, 1 цикл.
P.P.S. Это всё к тому, что можно собирать и сравнивать реальные результаты. Прсто на 8-битных глаза не разбегаются по нескольким страницам.
Копипаст, однако.
Добавлено через 14 минут(ы):
Чтобы боинги не падали не надо сравнивать числа с плавающей точкой операторами вида: ==, <=, >=, != и подобными. Читайте книжки по Си, там все черным по белому написано. Чтобы все таки сравнивать подобные числа, надо всё-таки погуглить как это делается правильно. Там много нюансов и неочевидных решений. Я предлагаю более простой и безопасный путь. Если это кого-то не устраивает: в счастливый путь к катастрофам..
Последний раз редактировалось payalnik; 05.09.2024 в 14:11.
Что бы боинги не падали Си/С++ вообще не используют, там Ада рулит. А вот для сравнения вещественных чисел между собой как раз и используют < > и так далее. Другое дело, когда нужно сравнить вещественную переменную с каким-то точным значением, например с нулем, тогда не используют == , а берут какую-то маленькую дельту, допустимую по условию задачи, и сравнивают с ней модуль числа, и никаких неприятностей там не возникает. Приводить же вещественное число к целому для сравнения это как раз то, как делать не нужно.
Из-за накопления вычислительной погрешности. Ну или даже такие просты примеры. Попробуйте сравнить через == числа x и y если они получены таким образом:
Код:x = 0.6 - 0.2 y = 0.2 + 0.2
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)