• графика Ещё заметил, что конвертация из чисел с плавающей точкой в 0…255 делается не всегда верно. Если брать Floor (X 255.0), то, чтобы получить 255, Х должен быть строго 1.0, а 0.999 — это уже 254. Если брать Round (X 255.0), то, чтобы получить 255, X должен быть в интервале от 509/510 до 510/510 в то время как, чтобы получить 254, X может быть во вдвое более широком интервале от 507/510 до 509/510. Чтобы сделать честную конвертацию, надо взять Min (255, Floor (X * 256.0)). Но так мало, кто делает.

    Вообще говоря, остаются нечестно поделённые инфинитезимали. Они, конечно, инфинитезимали, но получить их вручную как коэффициент в формуле проще простого.

    Для них можно написать такое:
    if X <= 0.5 then
    return Floor (X * 256.0);
    else
    return Ceiling (X * 256.0) — 1;
    end if;

    3/4, например. Для честности ему бы следовало быть 191, а не 192. Только 1/2 нельзя сконвертировать честно.

Replies (2)

  • @OCTAGRAM, ```
    var float2nbits = (n, f, v) => {
    if (!n) { return v; }
    var nextBit = (f > 0.5);
    return float2nbits(n-1, 2*((nextBit) ? (f-0.5) : f), (v << 1) + nextBit);
    }
    var float2byte = f => float2nbits(8, f, 0);
    ```

    Сначала написал
    `var nextBit = (n % 2) ? (f >= 0.5) : (f > 0.5);`
    потом подумал что бред получается, и решил, что чтобы было более или менее поровну, но глаза не резало на "круглых" значениях, то лучше
    `var nextBit = (n === 1) ? (f >= 0.5) : (f > 0.5);`
  • @OCTAGRAM, У тебя с нулём такая же ерунда будет, не только с 255. Если хочешь полуинтервал [0;1) равномерно на байт спроецировать, то однозначно — Floor(256.0*x). А непосредственно 1 при неограниченной точности не имеет статистической значимости и её можно обрезать через Min.
    Если у тебя нецелые представлены отрезком [0; 1] с ограниченной аюсолютной точностью представления Delta, то надо делать Floor((256.0-Delta)*x).