Вычисление погрешности от деления
- Войдите на сайт для отправки комментариев
Ср, 07/06/2017 - 09:48
Изучаю типы данных, чтобы в дальнейшем не наступать на грабли. Вычисление погрешности от деления проходит правильно - делю на 128 и умножаю на 128 (или сдвигаю на 7 вправо, зате на 7 влево), а разница между исходным числом 0x8FFFFFFF=2415919103 и результатом деления+умножения (0x8FFFFFFF>>7)<<7=2415918976 выводится неверно.
Должно быть 2415919103-2415918976=127, те потери от сдвига вправо семи единиц, а выводится 1879048192.
наверное я что-то неправильно преобразовал и загнал в дополнительный код, хотя тип данных беззнаковый. Что нужно исправить в формуле (строка 16)?
void setup()
{
Serial.begin(9600);
while (!Serial){; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("0xFF>>1=");Serial.println(0xFF>>1);
Serial.print("0x8FFFFFFF=");Serial.println(0x8FFFFFFF);
Serial.print("0x8FFFFFFF/128=");Serial.println(0x8FFFFFFF/128);
Serial.print("(0x8FFFFFFF/128)*128=");Serial.println((0x8FFFFFFF/128)*128);
Serial.print("0x8FFFFFFF>>7=");Serial.println(0x8FFFFFFF>>7);
Serial.print("(0x8FFFFFFF>>7)<<7=");Serial.println((0x8FFFFFFF>>7)<<7);
Serial.print("(unsigned long)0x8FFFFFFF -(unsigned long)(0x8FFFFFFF>>7)<<7=");Serial.println((unsigned long)0x8FFFFFFF -(unsigned long)(0x8FFFFFFF>>7)<<7);
Serial.print("2415919103-2415918976="); Serial.println(2415919103-2415918976);
Serial.print("(unsigned long)(-1)=");Serial.println((unsigned long)(-1));
}
void loop()
{
}
Serial.print:
0xFF>>1=127 0x8FFFFFFF=2415919103 0x8FFFFFFF/128=18874367 (0x8FFFFFFF/128)*128=2415918976 0x8FFFFFFF>>7=18874367 (0x8FFFFFFF>>7)<<7=2415918976 (unsigned long)0x8FFFFFFF -(unsigned long)(0x8FFFFFFF>>7)<<7=1879048192 2415919103-2415918976=127 (unsigned long)(-1)=4294967295
Читаем про приоритет операций С
у унарного минуса приоритет выше, чем у побитового сдвига
может это не погрешность от деления, а остаток?
Вам не кажется, что результат можно получить просто сделав AND 0x7F ?
у унарного минуса приоритет выше, чем у побитового сдвига
Спасибо, исправил ошибку :
void setup() { Serial.begin(9600); while (!Serial){; // wait for serial port to connect. Needed for native USB port only } Serial.print("0x8FFFFFFF=");Serial.println(0x8FFFFFFF); Serial.print("0x8FFFFFFF/128=");Serial.println(0x8FFFFFFF/128); Serial.print("(0x8FFFFFFF/128)*128=");Serial.println((0x8FFFFFFF/128)*128); Serial.print("0x8FFFFFFF>>7=");Serial.println(0x8FFFFFFF>>7); Serial.print("(0x8FFFFFFF>>7)<<7=");Serial.println((0x8FFFFFFF>>7)<<7); Serial.print("Variant 1: unsigned long)0x8FFFFFFF -(unsigned long)((0x8FFFFFFF>>7)<<7)");Serial.println((unsigned long)0x8FFFFFFF -(unsigned long)((0x8FFFFFFF>>7)<<7)); Serial.print("Variant 2: unsigned long)0x8FFFFFFF -((unsigned long)(0x8FFFFFFF>>7)<<7)");Serial.println((unsigned long)0x8FFFFFFF -((unsigned long)(0x8FFFFFFF>>7)<<7)); Serial.print("(unsigned long)(-1)=");Serial.println((unsigned long)(-1)); } void loop() { }результат:
Вы правы. А если делить на число не являющееся степенью двойки, то как заменить деление на AND?
Я в примере делил на 128 и для него маска остатка =0x7F=127=(128-1).
Если число не степень двойки, то никак на AND не заменишь. Но в С есть прекрасная апирацея %. Которая и есть остаток от целочисленного деления.