Я столкнулся с этой проблемой, потому что имел переменную-член только с get
without set
свойством
, что означает ее auto calculated
и not stored
в качестве столбца в the table
, поэтому его not exist
в table schema
, поэтому
blockquote>make sure
, что любая переменная-членnot auto calculated
доhave
agetter
иsetter
свойства
Если я правильно понял ваш вопрос, вам просто нужна часть после десятичной дроби, верно? Вам не нужна дробь (целочисленный числитель и знаменатель)?
Итак, у нас есть какое-то число, скажем 3,14159
, и мы хотим получить только 0,14159
. Предполагая, что наше число хранится в float f;
, мы можем сделать это:
f = f-(long)f;
Что, если мы вставим наше число, работает следующим образом:
0.14159 = 3.14159 - 3;
Это удаляет целую часть числа из числа float, оставляя только десятичную часть. Когда вы конвертируете число с плавающей запятой в длинное, оно отбрасывает десятичную часть. Затем, когда вы вычтите это из исходного числа с плавающей запятой, у вас останется только десятичная часть. Здесь нам нужно использовать long из-за размера типа float
(8 байтов в большинстве систем). Целое число (всего 4 байта во многих системах) не обязательно достаточно велико, чтобы покрыть тот же диапазон чисел, что и float
, но long
должно быть.
double frac(double val)
{
return val - trunc(val);
}
// frac(1.0) = 1.0 - 1.0 = 0.0 correct
// frac(-1.0) = -1.0 - -1.0 = 0.0 correct
// frac(1.4) = 1.4 - 1.0 = 0.4 correct
// frac(-1.4) = -1.4 - -1.0 = -0.4 correct
Простой и работы для-ve и +ve
Ваш метод предполагает, что в дробной части 16 бит (и, как отмечает Марк Рэнсом, это означает, что вы должны сдвинуть на 16 бит, то есть умножить на на 0x1000). Это могло быть неправдой. Показатель степени определяет, сколько бит находится в дробной части.
Чтобы выразить это в формуле, ваш метод работает, вычисляя (x modf 1.0)
как ((x << 16) mod 1 << 16) >> 16
, и это жестко запрограммированные 16, которые должны зависеть от экспоненты - точная замена зависит от вашего формата с плавающей запятой.
Я бы порекомендовал посмотреть, как modf реализован в системах, которые вы используете сегодня. Ознакомьтесь с версией uClibc.
http://git.uclibc.org/uClibc/tree/libm/s_modf.c
(По юридическим причинам он, похоже, имеет лицензию BSD, но вы, очевидно, захотите дважды проверить)
Некоторые макросы определены здесь .
В ваших константах есть ошибка. Вы в основном пытаетесь сдвинуть число влево на 16 бит, замаскировать все, кроме младших битов, а затем снова сдвинуть вправо на 16 бит. Сдвиг - это то же самое, что умножение на степень 2, но вы не используете степень 2 - вы используете 0xFFFF, который отключен на 1. Замена на 0x10000 заставит формулу работать должным образом.
Зачем вообще использовать числа с плавающей запятой для рисования линий? Вы можете просто придерживаться своей версии с фиксированной точкой и вместо этого использовать процедуру рисования линий на основе целых / фиксированных точек - приходит на ум Брезенхэм. Хотя у этой версии нет псевдонима, я знаю, что есть и другие.
Как я и подозревал, modf
не использует никакой арифметики как таковой - это все сдвиги и маски, посмотрите здесь . Разве вы не можете использовать те же идеи на своей платформе?
Я не совсем уверен, но думаю, что то, что вы делаете, неправильно, поскольку вы учитываете только мантиссу и полностью забываете показатель степени.
Вам нужно использовать показатель степени, чтобы сдвинуть значение мантиссы, чтобы найти действительную целую часть.
Описание механизма хранения 32-битных чисел с плавающей запятой см. здесь .