Многие многочисленные дубликаты этого вопроса задают вопрос о влиянии округления с плавающей запятой на конкретные числа. На практике легче понять, как это работает, глядя на точные результаты вычислений, а не просто на чтение. Некоторые языки предоставляют способы сделать это - например, преобразование float
или double
в BigDecimal
в Java.
Так как это вопрос, связанный с языком, ему нужны языковые агностические инструменты, такие как как Десятичный преобразование с плавающей запятой .
Применяя его к числам в вопросе, рассматриваемым как удваивает:
0,1 преобразуется в 0,1000000000000000055511151231257827021181583404541015625,
0,2 преобразуется в 0.200000000000000011102230246251565404236316680908203125,
0,3 конвертируется в 0,29999999999999999989897769753748434595763683319091796875 и
0,30000000000000004 преобразуется в 0,3000000000000000444089209850062616169452667236328125.
Добавление первых двух чисел вручную или в десятичный калькулятор, такой как Full Precision Calculator , показывает точную сумму фактических входов: 0.3000000000000000166533453693773481063544750213623046875.
Если округлить до эквивалента 0,3, ошибка округления будет 0.0000000000000000277555756156289135105907917022705078125. Округление до эквивалента 0,30000000000000004 также дает ошибку округления 0,0000000000000000277555756156289135105907917022705078125.
Возвращаясь к конвертеру с плавающей запятой, необработанный шестнадцатеричный показатель для 0.30000000000000004 равен 3fd3333333333334, который заканчивается четной цифрой и, следовательно, является правильным результатом.
До уровня 21 это, безусловно, невозможно на ненагруженном устройстве, и нет альтернативы с обычными разрешениями.
Если это нормально, требуют дополнительных прав администратора, возможно, возможно эмулировать подтверждение учетных данных очень слабо, с гораздо большим усилием, реализуя DeviceAdminReceiver.onPasswordSucceeded
. Заблокируйте экран, когда пароль успешно выполнит требуемое действие. Это может оказаться относительно сложным, потому что действие не всегда принимается (только если статус изменился), необходимо сохранить последний успех, связаться с получателем и т. Д.
. В качестве примечания стороны дважды проверьте использования и вашего дизайна, в большинстве случаев, когда используется createConfirmDeviceCredentialIntent, он фактически не требуется, и другие варианты дизайна могут устранить необходимость в нем.
Лучше предоставить подробную информацию о том, что именно вы пытаетесь защитить. Если это случай случайного доступа к устройству неавторизованным лицом, и создается постоянный токен, скажем, из некоторой службы oauth, может быть разумным либо повторно авторизовать через один и тот же поток входа в систему, либо сохранить некоторый hmac исходных учетных данных наряду с токеном, затем запрашивать и повторно проверять учетные данные, а не запрашивать учетные данные устройства. В качестве альтернативы, если этого достаточно для использования, вы можете использовать google login , чтобы разрешить доступ к вашему приложению / токену и проверить, что пользователь Google является тем же самым для сохраненного токена.
Лучший ответ, который я видел для этой ситуации, описан в сообщении в блоге:
Однако он воссоздает системные классы, которые private и вызывает AOSP-код, который не является общедоступным. Моя щедрость - лучший ответ, который не требует явного присвоения классов внутри проекта. Возможно, Smart Lock или другая огромная библиотека безопасности могут быть использованы для обратной совместимости, требуемой мне.