Гарантирует ли приведение к int после std :: floor правильный результат?

Здесь есть пара возможностей (и, пожалуйста, опубликуйте весь класс, если это не так).

1) Вы не инициализируете изображение правильно. 2) Ваш поток пуст, поэтому вы ничего не получаю

Я предполагаю, что student.getImage () имеет подпись байта [], поэтому сначала убедитесь, что эти данные фактически нетронуты и представляют изображение. Во-вторых - вы не указываете тип контента, который должен быть «image / jpg» или все, что вы используете.

Вот некоторый код шаблона, чтобы проверить его, я использую для этого Primefaces 2.

/** 'test' package with 'test/test.png' on the path */
@RequestScoped
@ManagedBean(name="imageBean")
public class ImageBean
{
    private DefaultStreamedContent content;

    public StreamedContent getContent()
    {
        if(content == null)
        {
            /* use your database call here */
            BufferedInputStream in = new BufferedInputStream(ImageBean.class.getClassLoader().getResourceAsStream("test/test.png"));
            ByteArrayOutputStream out = new ByteArrayOutputStream();

            int val = -1;
            /* this is a simple test method to double check values from the stream */
            try
            {
                while((val = in.read()) != -1)
                    out.write(val);
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }

            byte[] bytes = out.toByteArray();
            System.out.println("Bytes -> " + bytes.length);
            content = new DefaultStreamedContent(new ByteArrayInputStream(bytes), "image/png", "test.png");
        }

        return content;
    }
}

и некоторая разметка ...

<html 
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.prime.com.tr/ui"
>

    <h:head>

    </h:head>

    <h:body>
        <p:graphicImage value="#{imageBean.content}" />
    </h:body>
</html>

Если этот код работает, то вы настроены правильно. Несмотря на то, что это код мусора для потоков (не используйте его в процессе производства) , он должен дать вам возможность устранить неисправность. Я предполагаю, что вы можете что-то происходить в вашей JPA или другой базе данных, где вы байт [] пуст или он отформатирован неправильно. Кроме того, у вас может быть проблема с контентом.

Наконец, я бы клонировал данные из компонента, чтобы student.getImage () был только скопирован в новый массив, а затем использован. Таким образом, если у вас что-то неизвестное происходит (что-то еще перемещает объект или меняет байт [], вы не возитесь с вашими потоками.

Сделайте что-то вроде:

byte[] data = new byte[student.getImage().length]
for(int i = 0; i < data.length; i++)
  data[i] = student.getImage()[i];

, так что ваш bean-экземпляр имеет копию (или Arrays.copy () - независимо от того, что плавает ваша лодка). Я не могу подчеркнуть, что что-то простое, как этот / тип содержимого, как правило, неверно. Удачи вам.

38
задан Jesse Beder 11 February 2010 в 17:01
поделиться

5 ответов

Диапазон двойных является путем, больше, чем диапазон целых чисел на 32 или 64 бита, который является почему std::floor возвраты double. Кастинг к int должен быть прекрасным, пока это в соответствующем диапазоне - но знать, что double не может представить все целые числа на 64 бита точно, таким образом, можно также закончить с ошибками, когда Вы идете вне точки, в которой точность double такова, что различие между двумя последовательными удваивается, больше, чем 1.

28
ответ дан Jon Skeet 11 February 2010 в 17:01
поделиться

Если Вы хотите иметь дело с различными числовыми условиями и хотеть обработать различные типы преобразований управляемым способом, то, возможно, необходимо посмотреть эти Повышение. NumericConversion. Эта библиотека позволяет обрабатывать странные случаи (как из диапазона, округление, диапазоны, и т.д.)

Вот пример из документации:

#include <cassert>
#include <boost/numeric/conversion/converter.hpp>

int main() {

    typedef boost::numeric::converter<int,double> Double2Int ;

    int x = Double2Int::convert(2.0);
    assert ( x == 2 );

    int y = Double2Int()(3.14); // As a function object.
    assert ( y == 3 ) ; // The default rounding is trunc.

    try
    {
        double m = boost::numeric::bounds<double>::highest();
        int z = Double2Int::convert(m); // By default throws positive_overflow()
    }
    catch ( boost::numeric::positive_overflow const& )
    {
    }

    return 0;
}
5
ответ дан Anonymous 11 February 2010 в 17:01
поделиться

Большая часть стандартного математического использования библиотеки удваивает, но обеспечивает версии плавающие также. станд.:: floorf () является версией одинарной точности станд.:: пол (), если Вы предпочли бы не использовать, удваивается.

Редактирование: я удалил часть своего предыдущего ответа. Я заявил, что пол был избыточен при кастинге к интервалу, но я забыл, что это только верно для положительных чисел с плавающей точкой.

2
ответ дан Dan Olson 11 February 2010 в 17:01
поделиться
static_cast <int> (std::floor(x));

делает в значительной степени, что Вы хотите, да. Это дает Вам ближайшее целое число, округленное к - бесконечность. По крайней мере, пока Ваш вход находится в диапазоне, представимом ints. Я не уверен, что Вы подразумеваете 'под добавлением.5 и этажеркой, но это не будет иметь того же эффекта

И станд.:: пол возвращает двойное, потому что это является самым общим. Иногда Вы могли бы хотеть округлить плавание или удвоиться, но сохранить тип. Таким образом, раунд 1.3f к 1.0f, а не к 1.

Это было бы трудно сделать если станд.:: пол возвратил интервал (или по крайней мере у Вас будет дополнительный ненужный бросок, там замедляющий вещи).

, Если пол только выполняет округление себя, не изменяя тип, можно бросить это к интервалу, если/когда Вы должны.

Другая причина состоит в том, что диапазон удваивается, намного больше, чем тот из ints. Это не может быть возможно к раунду, который все удваивает до ints.

15
ответ дан jalf 11 February 2010 в 17:01
поделиться

В стандарте C ++ сказано (4.9.1):

«r-значение типа с плавающей запятой может быть преобразовано в r-значение целочисленного типа. Преобразование усекается, то есть дробная часть отбрасывается. Поведение не определено, если усеченное значение не может быть представлено в целевом типе ".

Таким образом, если вы конвертируете двойное значение в int, это число находится в диапазоне от int и необходимого округления стремится к нулю, тогда достаточно просто привести число к int:

(int) x;

7
ответ дан 27 November 2019 в 03:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: