#java
Вопрос:
Попытка преобразовать минуты в секунды с использованием двойных исходных данных,
так, например, 33,51 секунды (33 минуты 51 секунда) Как преобразовать это в int при преобразовании в seconeds только мой код на данный момент принял бы это, если бы для начала не было двойной точки, поэтому я использовал только ints, и, похоже, это работает, но когда у меня есть этот двойной, это не так, есть ли лучший подход к этому .
Вот мой код на данный момент
public class Runner { //fields setting up the variables String MembershipID; String name; int time ; //constructor1 filling in the details public Runner(String Mem, String na, int ti) { MembershipID = Mem; name = na; //This time = ti; } public String getMembershipID() { return MembershipID; } public String getName() { return name; } //setting it up for the main method from the constructor fields above public int getTime() { int mins = time *60; return mins; } public static void main(String[] args) { //initializing the membership name and time, Runner a = new Runner("RF23", "George Formsby", 33); //Creating a new instance of Runner, filling out the details from the sample data provided. Runner b = new Runner("RG89", "Neil Innes", 32); Runner c = new Runner("ST200", "Sandy Denny", 30); // With mem and na being represented from my constructor System.out.println("MembershipID is: " a.getMembershipID()); System.out.println("Name is: " a.getName()); System.out.println("Time in seconds: " a.getTime()); System.out.println("MembershipID is: " b.getMembershipID()); System.out.println("Name is: " b.getName()); System.out.println("Time is: " b.getTime()); System.out.println("MembershipID is: " c.getMembershipID()); System.out.println("Name is: " c.getName()); System.out.println("Time is: " c.getTime()); } }
Комментарии:
1. Вы уверены , что
33.51
это должно быть 33 минуты и 51 секунда? Что было бы33.70
в этом случае?2.
33.51
должно быть около 33 минут и 30,6 секунды.3. Извините, если я неправильно понял ваш вопрос, но не могли бы вы просто рассчитать все это, если 33,51% 1-секунды, а математический раунд(33,51/1) — минуты? Конечно, конечно, 33.51 не должны составлять 33 минуты и 30 секунд
4. плохая идея использовать двойник для десятичной арифметики. Вы можете представить с помощью int как часы*100 минут, а затем преобразовать обратно
5. Это похоже на использование неправильного типа данных для задания. 33 минуты и 51 секунда никогда не должны быть представлены двойником
33.51
. Вы могли бы использоватьDuration
, но если вы хотите придерживатьсяint
, он должен представлять количество секунд. В вашем примере это будет 2031 год ( 33 * 60 51 ).
Ответ №1:
Кажется, достаточно простая математика.
Преобразуйте минуты секунды всего в секунды
int minutes = ...; int seconds = ...; int totalSeconds = minutes * 60 seconds;
Преобразуйте минуты (в двойном размере) в секунды
double time = 12.33; int seconds = (int) (0.5 time * 60);
Пояснение: при округлении до an int
java отключает десятичные части. Мы хотим округлить до ближайшей секунды, что может быть тривиально выполнено (для положительных чисел!) добавив к нему 0,5, а затем приведя int
к.
ПРИМЕЧАНИЕ: Смотрите примечание ниже!
Преобразуйте секунды (как int) в минуты (как double)
int totalSeconds = ....; double time = time / 60.0;
Пояснение: В java синтаксическая конструкция x / y
считается «целочисленным делением», если x
и y
оба являются целочисленными типами данных ( byte
, short
, int
, long
, или char
). Это считается «делением с плавающей запятой», если x или y являются типом с плавающей запятой ( float
или double
). целочисленное деление будет отсекать десятичные цифры (поэтому оно округляется для положительных результатов и округляется для отрицательных результатов). Так 90 / 2
, например , решает 1
К. Нет 1.5
. С другой стороны, 90 / 2.0
решает 1.5
, потому что по крайней мере одно из двух чисел является двойным ( 2.0
является двойной константой, 2
является константой int). Следовательно, почему мы делим на 60.0
и не 60
.
NB: Важная вещь, о которой нужно подумать: ТОЧНОСТЬ.
Компьютеры не являются волшебными и double
точно определены как состоящие ровно из 64 бит.
Вы не можете хранить один из бесконечной последовательности вариантов в ограниченном пространстве хранения, поэтому компьютеры не могут идеально хранить числа. 64-разрядное пространство для хранения данных может предоставить вам самые 2^64
разные «опции». Если в хранилище хранится число, это означает 2^64
, что там может храниться не более чисел, и поэтому все остальные числа просто не могут быть им представлены. Кто-то должен выйти и определить, какие числа являются «благословенными» — способными храниться. Затем кто-то должен определить, что произойдет, если вы попытаетесь сохранить в них не благословенное число.
Для целочисленных типов данных это просто: int
(32-разрядные) могут хранить 2^32 числа. Какие числа благословенны? Просто -2^31
чтобы 2^31 -1
. Когда вы пытаетесь сохранить что-то выше или ниже этого, числа просто описывают круг:
int reallyLarge = Integer.MAX_VALUE; // this is 2^31-1. int surelyThisIsEvenLarger = reallyLarge 1;
На самом деле, surelyThisIsEvenLarger
это отрицательное число вместо этого. Он петлял вокруг.
Ибо double
и float
это намного сложнее. Даже между просто 0
и 1
есть бесконечные числа! Благословенные числа выбираются путем более или менее метания дротиков в числовую линию, фокусируя около половины дротиков вблизи 1.0
, при этом все меньше и меньше дротиков попадает в числовую линию по мере удаления от 1,0. В конечном счете, примерно 2^52
на «расстоянии» между любыми 2 дротиками больше, чем 1.0
даже.
Это немного похоже на то, как мы, люди, это делаем: мы вообще не можем «представлять» 1, разделенное на 3. 0.333333....
это никогда не кончается.
Что еще хуже, компьютеры считают в двоичном, а не десятичном формате. Итак, там , где мы, люди, можем, например, сделать «1, деленное на 10» (то 0.1
есть, это благословенное число в системе «человек записывает его десятичным числом на листе бумаги, в котором есть место примерно для 10 цифр»), компьютеры тоже не могут этого сделать.
Таким образом, большинство значений «возьмите это количество секунд и превратите их в двойное» на самом деле не благословлены, поэтому важно понимать, что происходит, когда вы пытаетесь сделать двойное, которое не благословлено: компьютер округлит его до ближайшего благословенного числа. Вы не можете запросить ошибку (сумму, на которую она округлена), или попросить ее не делать этого; double
во всяком случае, не с помощью.
Если вы сделаете достаточно математических вычислений для них, эти ошибки усугубятся и в конечном итоге будут совершенно неправильными. Это одна из многих причин, по которым вы определенно никогда, никогда не должны использовать double
для хранения денежных ценностей. Для мониторинга гонок вы сталкиваетесь с аналогичной ситуацией здесь, лучше не использовать их. Лучше выбрать атомную единицу и хранить в них. Например, почему бы не хранить в миллисе? Текущий рекорд самой быстрой мили-3:43.13. В «миллисе» это становится long fastestMile = 223130;
— нет необходимости вовлекать этих мерзких двойников с их странным округлым поведением.