Java умножает операционное поведение

Это является следствием использования dodge2 против dodge. Это ожидаемое поведение, изложенное здесь .

Может быть, вы хотите вместо обычного dodge?

library(ggplot2)
#fake data that mimics yours
set.seed(42)
error_hat <- runif(100)
error_tilde <- runif(100)
catagory <- c(rep("error_hat",length(error_hat)) , rep("error_tilde",length(error_tilde)))
error <- c(error_hat, error_tilde)
error_data<-data.frame(catagory,error)
ggplot(error_data, aes(x=error,group=catagory,fill=catagory))+
  geom_histogram(position="dodge", binwidth=0.03)+theme_bw()

Создано в 2019-01-15 пакетом представитель (v0.2.1) sup>

8
задан starblue 4 February 2009 в 17:20
поделиться

10 ответов

Действительно ли это очевидно? Я предполагаю, что это зависит от того, сколько времени Вы использовали Java и сколько раз необходимо было иметь дело с миллисекундами. Конечно, это должно быть хорошо для приблизительно до 24 дней...

Я думаю, что самая большая подсказка должна быть этим System.currentTimeMillis() возвраты a long. Это - хороший признак, что много миллисекунд могут стать большими. Тип переменной, которую Вы устанавливаете, должен быть хорошей подсказкой также.

Конечно, Вы также узнали это, если Вы сделаете арифметические операции с ints, то результат будет int с циклическим возвратом на переполнении. Достаточно ли это очевидно или не могло бы быть обсуждено, но это будет довольно бессмысленное обсуждение. В C# при включении проверки переполнения Вы нашли бы ошибку довольно быстро - но затем не многие разработчики делают это (действительно, я не делаю, хотя я, вероятно, должен).

8
ответ дан 5 December 2019 в 06:10
поделиться

Да, довольно очевидно при выполнении этого прежде. Любое время Вы видите строку чисел, умноженных, необходимо автоматически начать думать об ошибках целочисленного переполнения. В этом случае Вы установлены переполниться если expireTimeInDays больше чем 24. Технически необходимо думать о водосливных ошибках любое время, Вы работаете с целыми числами, но умножаетесь, группа их как это должна быть очень большим красным флагом.

7
ответ дан 5 December 2019 в 06:10
поделиться

Только для добавления к другим ответам я нашел полезным в прошлом определить константы (public static final long) такой как MILLISECS_DAY или MILLISECS_HOUR. Намного более читаемый и полезный.

1
ответ дан 5 December 2019 в 06:10
поделиться

Нет, это не очевидно.

Но доверяйте мне еще после нескольких лет практики и исправляющих ошибок как это, Вы становитесь очень разумными о целочисленных переполнениях и просто делаете правильную вещь, даже не думая об этом.

Это - что-то, что произошло со всеми. Определенно никакой знак плохой практики кода, незнания или около этого.

2
ответ дан 5 December 2019 в 06:10
поделиться

Можно быть интересно знать, что это покрыто "Трудными вопросами Java" Joshua Bloch и Neal Gafter.

alt text
(источник: javapuzzlers.com)

Вы найдете много других ловушек Java, прерываний и угловых случаев в той книге.

Я соглашаюсь с starblue, кто оставил комментарий. Добавьте L к числу.

3
ответ дан 5 December 2019 в 06:10
поделиться

Ваша переменная операнда и литеральные числа имеют интервал типа. Тип данных int имеет максимальное значение 2^31 - 1. Поэтому с такими большими количествами, типом данных международного продвижения переполнения к кажущемуся неправильному ответу.

В Вашем первом примере интервал только продвинут на длинное на присвоении на переменную, которая происходит после вычисления. Результатом вычисления является интервал.

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

3
ответ дан 5 December 2019 в 06:10
поделиться

Другой способ записать это

public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = (long) expireTimeInDays * 24 * 60 * 60 * 1000;
}

или

public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = expireTimeInDays * 24L * 60 * 60 * 1000;
}
1
ответ дан 5 December 2019 в 06:10
поделиться

Существует некоторый инструмент статического анализа (findbugs), который найдет подобные ошибки.

Числовая математика на компьютерах может быть твердой. Порядок операционных вопросов может влиять на точность и точность способами, которыми Вы не ожидаете. Математика даты может также быть удивительно хитрой. Часто лучше использовать стандартные программы Даты/Календаря вместо того, чтобы пытаться сделать математику самостоятельно, но те стандартные программы не являются лучшими разработанными в библиотеке классов Java.

1
ответ дан 5 December 2019 в 06:10
поделиться

Я не пытаюсь выровнять по ширине свою ошибку, но было бы замечательно, если бы компилятор Java был достаточно умен продвинуть интервал задолго до вычисления (после того как вычисление присваивается переменной типа долго),

Между прочим, я раньше работал с C/C++ и если это была программа C, у меня была та же проблема, но несколько лет назад я был более осторожным с этим видом операции.

Я уделю больше внимания в следующий раз (или переключусь на Python)... :D

0
ответ дан 5 December 2019 в 06:10
поделиться

При использовании FindBugs на коде, он обнаружит эту точную проблему. "ICAST: Результат броска целочисленного умножения к длинному". Пример FindBugs точно, что Вы делаете; вычисление дней в миллисекундах.

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

1
ответ дан 5 December 2019 в 06:10
поделиться
Другие вопросы по тегам:

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