Наконец-то смог откомпилировать проект и сделать несколько измерений. Так как результаты получились довольно объёмные, оформил их в виде отдельной статьи (в песочнице) с некоторыми дополнительными замечаниями.
1. сумма 0.6000006 и 0.03339874 — формата float недостаточно для вычислений с данной точностью.
Да нет. В большинстве случаев он достаточен. Формат float обеспечивает представление десятичных цифр в двоичном коде, гарантируя 7 верных десятичных цифр.
Вы как бы не учли, что если привести эти числа к одному порядку, получается уже 8 значащих цифр.
А как вы догадались, что округлить надо до 4 цифр? Глядя на полученный результат? А почему не до 5 или 6 знака после запятой, как здесь кто-то выше предлагал?
Можно и до 5 или 6, результат будет тот же. А до 4-х исходя из точности исходных данных, а именно 105.3256.
К сожалению, при попытке компиляции появляются ошибки,
например:
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp: In static member function 'static std::unique_ptr<ROADdecoder::Driver::IDataReadDriver> ROADdecoder::Driver::DataDriver::getIDataReadDriver(std::shared_ptr<unsigned char>&, PlatformDependencies::ROADUInt32, Endian::EndianType)':
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp:12:90: error: 'std::unique_ptr<Endian::IEndianConvertor>' is an inaccessible base of 'PlatformDependencies::Unique_ptr<Endian::IEndianConvertor>'
std::unique_ptr<IDataReadDriver> result(new DataReadDriver(aData, aLength, lconvertor));
^
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp: In static member function 'static std::unique_ptr<ROADdecoder::Driver::IDataReadDriver> ROADdecoder::Driver::DataDriver::getIDataReadDriver(ROADdecoder::Driver::DataContainer*, PlatformDependencies::ROADUInt32, Endian::EndianType)':
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp:23:90: error: 'std::unique_ptr<Endian::IEndianConvertor>' is an inaccessible base of 'PlatformDependencies::Unique_ptr<Endian::IEndianConvertor>'
std::unique_ptr<IDataReadDriver> result(new DataReadDriver(aData, aLength, lconvertor));
Я что-то не так делаю?
Почему вы не хотите выложить исполняемый файл(ы)?
1. сумма 0.6000006 и 0.03339874 — формата float недостаточно для вычислений с данной точностью.
2. умножение 0.06543455 на 139 — аналогично, при умножении необходимо иметь удвоенное количество разрядов для хранения результата.
3. деление 131 на 0.066 аналогично предыдущему. 1/0.066=15.151515...=15.(15) имеет бесконечное количество значащих цифр.
4. вычитание 105.3256 и 105.32 — здесь точности уже достаточно, и для получения корректного результата достаточно округлить результат до 4 цифр после запятой. Округление необходимо для отбрасывания погрешности, внесённой при преобразовании из 10-ого представления числа в двоичное. Продемонстрировать это можно, например, так:
Вообще, для проверки ваших математических выкладок я бы рекомендовал Вам использовать не Excel или калькулятор, а системы компьютерной алгебры. Например, в Wolfram Mathematica можно явно задавать точность чисел с плавающей точкой для обеспечения корректного результата:
Хотите точные операции с дробями — используйте fixed point арифметику.
Для точных рациональных вычислений нужно использовать специальные средства, например, класс «ratio» в c++, который хранит отдельно числитель и знаменатель в целочисленном виде.
Нет вопросов к социальному статусу автора.
Нет фатальной ошибки в том, что формат с ограниченной точностью имеет ограниченную точность.
Если вы хотите убедить, что в реализации IEEE754 есть ошибки — то надо не сюда писать, а в комитет по стандартизации.
Если вы изобрели новую, улучшенную технологию обработки чисел с плавающей точкой — то её надо срочно патентовать, пока этого не сделал кто-то другой.
Если вы боитесь, что «такой неожиданный результат из придуманных нами, случайно не выскочит при контроле, например, за ядерной установкой», то в любом случае уже поздно что-то менять — в современных процессорах стандарт реализован аппаратно.
Раз об этом зашла речь, а к чему вы, собственно, близки? Если вы далеки от бухгалтерии, математики и программирования, но при этом испытываете потребность решать фундаментальные ограничения чисел с плавающей точкой.
Я думаю, что вы согласитесь, что во временной области аудио данные в пределах 4 семплов изменяются медленно
Не соглашусь, потому что такая формулировка как минимум некорректна. Но дело вовсе не в этом.
Если в результате вашего алгоритма на краях областей возникают разрывы, это приведёт к появлению искажений во всей области частот, и особенно на частотах близких к частоте Найквиста. Также возможно, что полезная информация на них будет вообще полностью подавлена и подменена паразитными гармониками.
Эффект Гиббса же я упомянул прямо с противоположной целью — как искажение, которое хорошо видно графически (в jpeg) и практически не слышно в звуке — mp3.
Очевидно для тех, кому смотреть на жизнь других (причём вымышленных) интереснее, чем жить самому. И вообще, я бы поостерёгся воспринимать голливудское кино как источник информации и уж тем более руководство к действию.
В реальной жизни самопожертвование возникает в намного менее прозаичных условиях — на войне или опасном производстве. Или когда мать голодает ради того, чтобы её ребёнок мог поесть. Но в таких случаях людьми движет вовсе не желание геройства, а чувство долга.
В такой формулировке возникает конфликт интересов — стремиться убить врага или позволить ему убить себя? Допустим, можно и убить, и умереть — но если враг только один. А если несколько? А если у тебя семья, своей смертью ты и её в жертву приносишь. А приносить в жертву других — это уже не геройство. Опять конфликт интересов.
Вы как бы не учли, что если привести эти числа к одному порядку, получается уже 8 значащих цифр.
Можно и до 5 или 6, результат будет тот же. А до 4-х исходя из точности исходных данных, а именно 105.3256.
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp: In static member function 'static std::unique_ptr<ROADdecoder::Driver::IDataReadDriver> ROADdecoder::Driver::DataDriver::getIDataReadDriver(std::shared_ptr<unsigned char>&, PlatformDependencies::ROADUInt32, Endian::EndianType)':
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp:12:90: error: 'std::unique_ptr<Endian::IEndianConvertor>' is an inaccessible base of 'PlatformDependencies::Unique_ptr<Endian::IEndianConvertor>'
std::unique_ptr<IDataReadDriver> result(new DataReadDriver(aData, aLength, lconvertor));
^
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp: In static member function 'static std::unique_ptr<ROADdecoder::Driver::IDataReadDriver> ROADdecoder::Driver::DataDriver::getIDataReadDriver(ROADdecoder::Driver::DataContainer*, PlatformDependencies::ROADUInt32, Endian::EndianType)':
..\..\..\..\ROAD-development\ROADcodec\ROADdecoder\Driver\DataDriver.cpp:23:90: error: 'std::unique_ptr<Endian::IEndianConvertor>' is an inaccessible base of 'PlatformDependencies::Unique_ptr<Endian::IEndianConvertor>'
std::unique_ptr<IDataReadDriver> result(new DataReadDriver(aData, aLength, lconvertor));
Я что-то не так делаю?
Почему вы не хотите выложить исполняемый файл(ы)?
1. сумма 0.6000006 и 0.03339874 — формата float недостаточно для вычислений с данной точностью.
2. умножение 0.06543455 на 139 — аналогично, при умножении необходимо иметь удвоенное количество разрядов для хранения результата.
3. деление 131 на 0.066 аналогично предыдущему. 1/0.066=15.151515...=15.(15) имеет бесконечное количество значащих цифр.
4. вычитание 105.3256 и 105.32 — здесь точности уже достаточно, и для получения корректного результата достаточно округлить результат до 4 цифр после запятой. Округление необходимо для отбрасывания погрешности, внесённой при преобразовании из 10-ого представления числа в двоичное. Продемонстрировать это можно, например, так:
Вообще, для проверки ваших математических выкладок я бы рекомендовал Вам использовать не Excel или калькулятор, а системы компьютерной алгебры. Например, в Wolfram Mathematica можно явно задавать точность чисел с плавающей точкой для обеспечения корректного результата:
In[1]:= 105.3256`7 - 105.32`7
Out[1]= 0.0056
In[2]:= 131/0.066`7
Out[2]= 1984.848
Для точных рациональных вычислений нужно использовать специальные средства, например, класс «ratio» в c++, который хранит отдельно числитель и знаменатель в целочисленном виде.
Нет фатальной ошибки в том, что формат с ограниченной точностью имеет ограниченную точность.
Если вы хотите убедить, что в реализации IEEE754 есть ошибки — то надо не сюда писать, а в комитет по стандартизации.
Если вы изобрели новую, улучшенную технологию обработки чисел с плавающей точкой — то её надо срочно патентовать, пока этого не сделал кто-то другой.
Если вы боитесь, что «такой неожиданный результат из придуманных нами, случайно не выскочит при контроле, например, за ядерной установкой», то в любом случае уже поздно что-то менять — в современных процессорах стандарт реализован аппаратно.
Первая же ссылка в google на запрос «floating point issues»:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Я вижу противоречие. Разве у вас в заголовке не написано — «Новый Алгоритм Сжатия»? Алгоритм сжатия без концепции сжатия?
Не соглашусь, потому что такая формулировка как минимум некорректна. Но дело вовсе не в этом.
Если в результате вашего алгоритма на краях областей возникают разрывы, это приведёт к появлению искажений во всей области частот, и особенно на частотах близких к частоте Найквиста. Также возможно, что полезная информация на них будет вообще полностью подавлена и подменена паразитными гармониками.
Эффект Гиббса же я упомянул прямо с противоположной целью — как искажение, которое хорошо видно графически (в jpeg) и практически не слышно в звуке — mp3.
Очевидно для тех, кому смотреть на жизнь других (причём вымышленных) интереснее, чем жить самому. И вообще, я бы поостерёгся воспринимать голливудское кино как источник информации и уж тем более руководство к действию.
В реальной жизни самопожертвование возникает в намного менее прозаичных условиях — на войне или опасном производстве. Или когда мать голодает ради того, чтобы её ребёнок мог поесть. Но в таких случаях людьми движет вовсе не желание геройства, а чувство долга.