英文:
How do I make this program return numbers after the decimal?
问题
这个程序是可以工作的,但是当我输入数字时,它返回的数字只有 .0(例如 1.0、2.0、3.0),而我希望它能返回小数点后的正确数字。
我知道这与数字是整数有关,但我不确定如何进行转换。我该如何修复这个问题?
编辑:如果这让人感到困惑,我想要的是程序以例如 5.7、4.9、2.4 的格式返回结果,但程序只返回 1.0、4.0、6.0。
package hw3;
import java.util.Scanner;
import java.util.ArrayList;
public class MovingAverage {
private QueueX queue;
private int size;
private double sum = 0; // 将 sum 的类型改为 double
/** 初始化数据结构。 */
public MovingAverage(int size) {
this.queue = new QueueX();
this.size = size;
}
// 检查队列的和、大小和平均值
public double next(int val) {
sum += val;
queue.enqueue(val);
if (queue.size() <= size) {
return sum / queue.size();
}
sum -= queue.dequeue();
return sum / size;
}
// 请勿更改主方法
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入一个数字以指定窗口大小:");
int window = input.nextInt();
MovingAverage m = new MovingAverage(window);
ArrayList<Double> arrList = new ArrayList<Double>();
for (int i = 0; i < window + 5; i++) {
System.out.print("请输入一个要添加到窗口的数字:");
int num = input.nextInt();
double avg = m.next(num);
System.out.println("添加上述数字后的平均值为:" + avg);
arrList.add(avg);
}
input.close();
System.out.println("序列中的平均值为:" + arrList);
}
}
英文:
This program works but when I input my numbers it return numbers with only .0 (ex 1.0, 2.0, 3.0) when i want it to give the correct number after the decimal.
I know it has something to do with the numbers being integers but Im not sure how to go about converting. How do I fix this?
EDIT: Sorry if its confusing. What I want is the program to give me the results in the format of ex. 5.7 or 4.9 or 2.4 but the program returns only 1.0 or 4.0 or 6.0
package hw3;
import java.util.Scanner;
import java.util.ArrayList;
public class MovingAverage {
private QueueX queue;
private int size;
private long sum = 0;
/** Initialize your data structure here. */
public MovingAverage(int size) {//
this.queue = new QueueX();
this.size = size;
}
// checks sum, size and average of the queue
public double next(int val) {
sum += val;
queue.enqueue(val);
if (queue.size()<=size) {
return sum/queue.size();
}
sum-= queue.dequeue();
return sum/size;
}
// DO NOT CHANGE THE MAIN METHOD
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Please enter a number to specify the window size: ");
int window = input.nextInt();
MovingAverage m = new MovingAverage(window);
ArrayList<Double> arrList = new ArrayList<Double>();
for (int i = 0; i < window + 5; i++) {
System.out.print("Please enter a number to be added into the window: ");
int num = input.nextInt();
double avg = m.next(num);
System.out.println("The average after adding the above number is: " + avg);
arrList.add(avg);
}
input.close();
System.out.println("Averages in the sequence are: " + arrList);
}
}
答案1
得分: 1
返回这行代码:
```java
return sum/queue.size();
这里有很多内容。
sum
是一个 long 型。queue.size()
是一个 int 型。方法的返回类型是 double,所以无论发生了什么,最终都会变成一个 double 值。
Java 的工作方式是按照以下确切的顺序进行的:首先,sum/queue.size()
的计算结果是什么,只有在这完成之后,下一步('将其转换为 double')才会开始。但这已经太晚了。
x / y
,其中 x 是 int,y 是 long,首先将 x 升级为 long,然后执行整数除法:进行除法运算,然后只需拿起斧头,砍掉小数部分(因此正数的情况会向下舍入,但负数的情况会向上舍入)。
所以,假设你的 sum 是 18,你的 count 是 4,你会计算 18/4,结果是 4,而不是 4.5。
然后将这个 4 转换为 double,现在你有了 4.0。
解决你的第一个问题
首先将计数器设为 double:return sum / (double) queue.size();
。现在这是'将这个 long 除以这个 double',它通过将 long 转换为 double,然后进行除法运算,这将得到 4.5。
但是,你还有第二个更复杂的问题。double 是一种 64 位的数据类型。基本逻辑表明,最多只能有 2^64 个不同的数字可以用 double 表示。这是一个问题;你可能认为几乎所有可能的数字都可以用它表示,但事实并非如此。实际上,它是一组'神圣的数字',可以由 double 表示(而且越接近 0,就有越多的神圣数字)。任何基于 double 的操作的结果会被__悄悄地__四舍五入到最近的神圣数字。神圣数字很让人头疼,因为从二进制的角度来看,它们在十进制中没有太多意义,因此奇怪的事情(例如 0.1+0.2)甚至无法正常工作。
解决第二个问题
这意味着 double 值通常会含有误差,你需要在打印时指定期望的误差。最好的方法是使用格式化函数:String.format(" %.5f", theDouble);
会按照规则进行格式化:小数点后最多 5 位数字。
或者,如果你想要更精确的计算,可以使用 BigDecimal
,但请注意,除法是棘手的(1/3 是 0.3333333 - 无限循环,因此如果不配置舍入规则,无法用 BigDecimal
进行计算)。
<details>
<summary>英文:</summary>
Take this line of code:
return sum/queue.size();
There's a lot going on here.
`sum` is a long. `queue.size()` is an int. The method's return type is `double`, so whatever happens here, somehow it all ends up as a double.
The way java works is in this exact order: First, `sum/queue.size()` is resolved to whatever it is, and only after that's all done does the next step ('make that a double') kick in. Which is too late.
`x / y`, where x is an int and y is a long, is done by first upgrading x to a long, and then doing integer division: Do the division, and just take an axe and lop off the decimal part (so, round down for positive numbers, but round up for negative numbers).
So, let's say your sum is 18, and your count is 4, you do 18/4 which is just 4. Not 4.5.
This 4 then gets turned into a double, so now you have 4.0.
## Fix to first of your two problems
Make your counter a double first: `return sum / (double) queue.size();`. Now it's 'divide this long by this double' which is done by converting the long to a double and then doing the division, which will get you 4.5.
But, you have a second, more complicated problem. A double is a datatype of 64-bit. Using basic logic, that means that there are only at most 2^64 different numbers in existence that can be represented by a double. Which is a problem; you'd think that literally every possible number ever can be represented by it, but __that is not true__. Instead it's a set of 'blessed numbers' which can be represented by double (and the closer you are to 0, the more blessed numbers there are). Any result of any double-based operation is __silenty__ rounded to the nearest blessed number. Blessed numbers are annoying in that they make some sense if looking at in binary, but not in decimal, so weird stuff (like 0.1+0.2) doesn't even work right.
## Fix to the second
That means that doubles tend to have errors in them, and you need to print them only by specifying how much error you expect. This is best done with format: `String.format("%.5f", theDouble);` will format according to the rule: No more than 5 digits after the comma.
Alternatively, if you want perfection, there is `BigDecimal` but note that division is tricky (1/3 is 0.3333333 - infinite, so without configuring rounding rules, cannot be done to a BD).
</details>
# 答案2
**得分**: 0
```java
public double next(int val) {
if(queue.size() == size)
sum -= queue.removeFirst();
queue.addLast(val);
sum += val;
return (double)sum / queue.size();
}
当你想使用 /
运算符时,请注意参数的类型。至少其中一个应为 double
或 float
。
int a = 9;
int b = 2;
double res = a / b; // 4
即 9 / 2 = 4
- 然后将此值转换为 double
,得到 4.0
double a = 9;
int b = 2;
double res = a / b; // 4.5
即 9.0 / 2.0 = 4.5
- 首先将所有操作数转换为 double
,然后进行除法运算
在两个参数均为 int
(或 long
)的情况下,
<details>
<summary>英文:</summary>
public double next(int val) {
if(queue.size() == size)
sum -= queue.removeFirst();
queue.addLast(val);
sum += val;
return (double)sum / queue.size();
}
Whey you want to use `/` pay attention on arguments. At least one of the should be `double` or `float`.
int a = 9;
int b = 2;
double res = a / b; // 4
*i.e. `9 / 2 = 4` - and then convert this value to double `4.0`*
double a = 9;
int b = 2;
double res = a / b; // 4.5
*i.e. `9.0 / 2.0 = 4.5` - first convert all operands to `double` then do division*
In case of both arguments `int` (or `long`), then
</details>
# 答案3
**得分**: -1
不确定我是否理解正确,但如果您想将数字显示为没有小数点的普通整数,那么与您在数组列表变量中使用 double 有关。如果您的确打算使用 double,但不想以这种方式显示,那么在打印时,即在您的 sout 中,您可以将值从 `var` 替换为 `(int)var`,甚至是 `(int)Math.round(var)`(以便在计算平均值时出现一些分数时可以四舍五入)。
<details>
<summary>英文:</summary>
Not sure if I understand it correctly, but if you want to display the numbers as normal integers without decimal points then it has something to do with you using double as avg and in your array list variables. If that was indeed your intention to use double but not display as such then while printing, ie, in your sout you can replace the value from `var` to `(int)var` or even `(int)Math.round(var)` (for you to round it off incase you have some fractions when avg is being calculated).
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论