C++使用 CEIL 和长度输出不正确的值

C++ using ceil and length outputs incorrect value

本文关键字:输出 不正确 使用 CEIL C++      更新时间:2023-10-16

这个应用程序在Java中收到正确的输入后,输出一个数字。 输入 1 如下所示:

  • 3 2

  • 1000

  • 1010

  • 1999

输出将为:2

对于输入 2:

  • 2 1

  • 0

  • 1000

输出将为:1

public class Application {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int k = input.nextInt();
int[] c = new int[200001];
for(int a = 0; a < n; a++){
int b = input.nextInt();
c[b]++;
c[b+1000]--;
}
int Requests = 0;
int maxRequests = 0;
for(int a = 0; a < c.length; a++){
Requests += c[a];
if(Requests > maxRequests){
maxRequests = Requests;
}
}
System.out.println((int)(Math.ceil(((maxRequests+0.0)/k) - 0.000000001)+0.2));
}  

我已经在C++中制作了这个应用程序,但问题是对于 input1,它输出"1",对于输入 2 = "2"。这是不正确的。

我的代码如下所示:

int main() {
int n;
int k;
cin >> n;
cin >> k;   
std::vector<int> c (200001);
for(int i = 0; i < n; i++)
{
int b;
cin >> b;
c[b]++;
c[b+1000]--;
}
int Requests = 0;
int maxRequests = 0;
for(int a = 0, length = sizeof(c); a < length; a++)
{
Requests += c[a];
if(Requests > maxRequests){
maxRequests = Requests; 
}
}
int x = ceil(((((maxRequests+0.0)/k) - 0.000000001)+0.2));        
cout << x;
return 0;
}

在过去的 4 个小时里,我一直在试图解决这个问题,现在是凌晨 4 点,我知道我应该读一本书,我在这里问就像万不得已。我的代码有什么问题?

据我所知,在这两种情况下,结果都应该2。在第二种情况下,数组中的值将是 1、-1 和大量 0。最大值为 1。1-0.00000001/1 +0.2 = 1.199999999(给或拿 9 或 2(。这显然大于 1,小于 2,因此ceil将其四舍五入为2

就C++实现它而言,我可能会以不同的方式完成这项工作。特别是,我会利用一些标准算法来为我处理部分工作。您正在执行的部分操作:

for(int a = 0; a<c.size(); a++)
{
Requests += c[a];

。是std::partial_sum已经做的事情。诀窍是partial_sum需要一个迭代器来告诉它在哪里存放结果。现在,我们可以(例如(将结果写入向量,然后扫描向量以找到最大的项:

std::vector<int> maxes;
std::partial_sums(c.begin(), c.end(), std::back_inserter(maxes));
int maxRequests = *std::max_element(maxes.begin(), maxes.end());

至少对我来说,当我们真的只想要一个值向量时,写一个完整的值向量似乎是相当浪费的:我们迄今为止见过的最大的一个。一种可能性是创建一个迭代器来做到这一点(我知道这比任何人都想的要长 - 幸运的是,它主要只是样板,所以暂时不需要太关心:

template <class T>
class keep_max_t {
T *val;
public:
using iterator_tag = std::output_iterator_tag;
using value_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
keep_max_t(T &t) : val(&t) {
*val = std::numeric_limits<T>::min();
}
keep_max_t &operator=(T new_val) { 
*val = std::max(*val, new_val);
return *this; 
}
keep_max_t &operator++() { return *this; }
keep_max_t &operator++(int) { return *this; }
keep_max_t &operator*() { return *this; }
};
template <class T>
keep_max_t<T> keep_max(T &v) { return keep_max_t<T>(v); }

现在我们可以计算部分和,并更直接地保留最大值:

int maxRequests;
std::partial_sum(c.begin(), c.end(), keep_max(maxRequests));

现在让我们看一下您正在做的计算:

int x = ceil(((((maxRequests+0.0)/k) - 0.000000001)+0.2));

从中间开始:(maxRequests+0.0)基本上只是获取maxRequests值的一种有点奇怪的方式,但从int转换为double。我们想要一个双精度型(或至少是一些浮点类型(,因为下一步将结果除以k

不过,我们这样做更简单一些:使k成为double,当我们做maxRequests / k时,编译器会自动将maxRequests转换为double,,并在双精度浮点数学中进行除法。因此,我们可以将其简化为:

double k;
cin >> k;
// ...
int x = ceil((maxRequests/k) // ...;

从那里开始,事情变得非常奇怪 - 由于我仍然不太理解的原因,我们减去一个数字,然后添加另一个数字。我们可以提前将它们加在一起,得到:

std::ceil((maxRequests / k) + 0.199999999);

最后,我们都知道乘法和除法比加减法具有更高的优先级,因此我们可以删除多余的括号,因此这变成了:

std::ceil(maxRequests / k + 0.199999999);

我仍然不确定魔术0.199999999是什么意思,但除了那个神奇的数字之外,它现在相当可读。

当然,我们无疑也希望在函数中进行这种计算,而不是将所有内容都塞进main

然而,为了便于测试,我们可以将测试输入值放入main,并将它们馈送到我们的函数中(并打印出结果(。将所有这些放在一起,我们最终可能会得到这样的代码:

#include <iostream>
#include <vector>
#include <numeric>
#include <sstream>
#include <cmath>
#include <chrono>
#include <utility>
#include <algorithm>
#include "keeper.h"
int compute_result(std::istream &input) {
int n;
double k;
input >> n;
input >> k;
std::vector<int> c(200001);
for (int i = 0; i < n; i++)
{
int b;
input >> b;
c[b]++;
c[b + 1000]--;
}
int maxRequests;
std::partial_sum(c.begin(), c.end(), keep_max(maxRequests));
return std::ceil(maxRequests / k + 0.199999999);
}
int main() {
using std::cin;
std::stringstream input1{ "3 2 1000 1010 1999" };
std::stringstream input2{ " 2 1 0 1000" };
std::cout << "First result: " << compute_result(input1) << "n";
std::cout << "Second result: " << compute_result(input2) << "n";
}

。其中 "keeper.h" 包含上面显示的迭代器。