Вычисление погрешности от деления

Lims
Offline
Зарегистрирован: 07.06.2017

Изучаю типы данных, чтобы в дальнейшем не наступать на грабли.  Вычисление погрешности от деления проходит правильно - делю на 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

 

okta
Offline
Зарегистрирован: 10.01.2015

Читаем про приоритет операций С

у унарного минуса приоритет выше, чем у побитового сдвига

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

может это не погрешность от деления, а остаток?

Вам не кажется, что результат можно получить просто сделав  AND 0x7F ? 

Lims
Offline
Зарегистрирован: 07.06.2017

okta пишет:
Читаем про приоритет операций С

у унарного минуса приоритет выше, чем у побитового сдвига

Спасибо, исправил ошибку :

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() 
{
}

результат:

0x8FFFFFFF=2415919103
0x8FFFFFFF/128=18874367
(0x8FFFFFFF/128)*128=2415918976
0x8FFFFFFF>>7=18874367
(0x8FFFFFFF>>7)<<7=2415918976
Variant 1: unsigned long)0x8FFFFFFF -(unsigned long)((0x8FFFFFFF>>7)<<7)127
Variant 2: unsigned long)0x8FFFFFFF -((unsigned long)(0x8FFFFFFF>>7)<<7)127
(unsigned long)(-1)=4294967295

 

 

Lims
Offline
Зарегистрирован: 07.06.2017

DetSimen пишет:
может это не погрешность от деления, а остаток?
Да, остаток. Имел ввиду расхождения возникающие при  целочисленном делении нечетного числа с большим колич 1 в младших разрядах .

DetSimen пишет:
Вам не кажется, что результат можно получить просто сделав  AND 0x7F ?

Вы правы. А если делить на число не являющееся степенью двойки, то  как заменить деление на  AND?

Я в примере делил на 128 и для него маска  остатка =0x7F=127=(128-1).

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Если число не степень двойки, то никак на AND не заменишь.  Но в С есть прекрасная апирацея %.  Которая и есть остаток от целочисленного деления.