简体   繁体   English

ACM问题。 我的代码有什么问题?

[英]A acm problem. What's wrong in my code?

The text of problem: 问题文字:

Input : The input stream contains a set of integer numbers Ai (0 ≤ Ai ≤ 1018). 输入 :输入流包含一组整数Ai(0≤Ai≤1018)。 The numbers are separated by any number of spaces and line breaks. 数字由任意数量的空格和换行符分隔。 A size of the input stream does not exceed 256 KB. 输入流的大小不超过256 KB。

Output : For each number Ai from the last one till the first one you should output its square root. 输出 :对于从最后一个到第一个的每个数字Ai,应输出其平方根。 Each square root should be printed in a separate line with at least four digits after decimal point. 每个平方根应打印在单独的行中,小数点后至少应有四位数字。

Sample 样品
input: 输入:

1427  0   

876652098643267843 5276538

output: 输出:

2297.0716
936297014.1164
0.0000
37.7757

Time Limit: 2.0 second 时限:2.0秒
Memory Limit: 16 MB 内存限制:16 MB

C and C++ programs are compiled on the server by the 32-bit Microsoft Visual C++ 2010. Until August 3, 2010 Intel C++ Compiler 7.0 was used. C和C ++程序由32位Microsoft Visual C ++ 2010在服务器上编译。在2010年8月3日之前,一直使用Intel C ++ Compiler 7.0。 You can download a free copy of Microsoft Visual Studio 2010 Express on this page. 您可以在此页面上下载Microsoft Visual Studio 2010 Express的免费副本。 The compiler is invoked with the following parameters: 使用以下参数调用编译器:

// C
cl /TC /MT /EHsc /O2 /W3 /Za /D "_CRT_SECURE_NO_WARNINGS" 
   /D "_CRT_SECURE_NO_DEPRECATE" /D "ONLINE_JUDGE"

// C++
cl /TP /MT /EHsc /O2 /W3 /Za /D "_CRT_SECURE_NO_WARNINGS" 
   /D "_CRT_SECURE_NO_DEPRECATE" /D "ONLINE_JUDGE"

This is my solution of this problem in gcc 4.3: 这是我在gcc 4.3中解决此问题的方法:

#include <iostream>
#include <list>
#include <string>
#include <sstream>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <stdio.h>

void sqrt_f(double n)
{
    printf ( "%.4f\n", sqrt( static_cast<double>( n ) ) );
}

int main()
{
    std::list<double> numbers;
    std::string sInput;
    getline( std::cin, sInput );
    std::istringstream parse( sInput );
    double tmp;
    while ( parse >> tmp )
        numbers.push_front( tmp );
    std::for_each(numbers.begin(), numbers.end(), sqrt_f);
    return 0;
}

But Judgement result is: wrong answer (test1) 但是判断结果是:答案错误(test1)

What's the problem? 有什么问题?

Warning: when I wrote this, the question was still on the code-review site, so it's written primarily as a code review. 警告:当我写这篇文章时,问题仍然在代码审查站点上,因此它主要是作为代码审查来编写的。 The part that applies primarily here on SO (fixing the input problem) is only barely mentioned in passing. 此处仅提及了主要适用于SO(解决输入问题)的部分。

For the moment, I'm going to assume that you've fixed the problem @Jeff Mercado pointed out to get code something like this: 目前,我将假定您已解决了@Jeff Mercado指出的获取问题的问题,例如:

#include <iostream>
#include <list>
#include <string>
#include <sstream>
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <stdio.h>

void sqrt_f(double n)
{
    printf ( "%.4f\n", sqrt( static_cast<double>( n ) ) );
}

int main()
{
    std::list<double> numbers;
    std::string sInput;
    while (getline( std::cin, sInput )) {  // added `while` to process all input
        std::istringstream parse( sInput );
        double tmp;
        while ( parse >> tmp )
            numbers.push_front( tmp );
    }
    std::for_each(numbers.begin(), numbers.end(), sqrt_f);
    return 0;
}

Then, I'm going to ignore the question you actually asked (about correctness) and just review the (rewritten) code, assuming that it meets the requirements. 然后,我将忽略您实际提出的问题(关于正确性),并假设满足要求,仅查看(重写)代码。

void sqrt_f(double n)
{
    printf ( "%.4f\n", sqrt( static_cast<double>( n ) ) );
}

I see three things here I don't particularly like: 我在这里看到了我特别不喜欢的三件事:

  1. Using printf in C++. 在C ++中使用printf。 iostreams are generally preferred (though as we'll see, they are more verbose in this case). iostream通常是首选(尽管我们将看到,在这种情况下,它们更为冗长)。
  2. The static_cast seem to be entirely extraneous ( n is already a double). static_cast似乎完全无关紧要( n已经是一个双精度)。
  3. Poor separation of concerns. 关注点分离差。 You're combining computation with I/O. 您正在将计算与I / O相结合。

    std::list<double> numbers;

I don't see much reason to use std::list here. 我没有太多理由在这里使用std::list You're only inserting at one end, and traversing beginning to end. 您只是在一端插入,然后从头到尾遍历。 The primary reason to use std::list is if you're going to insert/delete somewhere in the middle of the list. 使用std::list主要原因是,如果要在列表中间插入/删除某处。 Even then it's not necessarily the best choice, but when you only need to insert at one end, it's almost certainly the wrong choice. 即使这样,也不一定是最佳选择,但是当您只需要在一端插入时,几乎肯定是错误的选择。

std::string sInput;
while (getline( std::cin, sInput )) {  // added `while` to process all input
    double tmp;
    while ( parse >> tmp )
        numbers.push_front( tmp );
}

I don't see any real reason to use std::getline here. 我没有在这里使用std::getline任何真正原因。 getline is useful primarily when your input has line-oriented formatting, but here it's just a stream of doubles separated by some arbitrary amount of white space. getline主要在您的输入具有面向行的格式时很有用,但是在这里,它只是由一些任意数量的空格分隔的双精度流。 For that, you appear to have added extra complexity without gaining much functionality in return. 为此,您似乎增加了额外的复杂性,而没有获得很多功能。

I'm also less than excited about the loop while (parse >> tmp) . 我对while (parse >> tmp)的循环也很兴奋。 It's certainly better than some alternatives, but I'd rather use std::copy with (in this case) an std::istream_iterator<double> to copy the values into a collection. 它肯定比某些替代方法要好,但是我宁愿使用std::copystd::istream_iterator<double> (在这种情况下)将值复制到集合中。

I'm not particularly excited about how you're using the collection here either. 我对您如何在这里使用收藏也不感到特别兴奋。 First of all, you're reversing the order by using push_front . 首先,使用push_front反转顺序。 At least to me, it seems like it would be easier to understand if you added the numbers to the collection in their original order, then walked through the collection backwards. 至少对我来说,如果将数字按原始顺序添加到集合中,然后向后浏览集合,似乎会更容易理解。

    std::for_each(numbers.begin(), numbers.end(), sqrt_f);

...and here's the culprit responsible for the poor separation of responsibility in sqrt_f . ...这是导致sqrt_f中责任分工sqrt_f It's been something like 15 years since the STL came to C++, and in that time I doubt I've seen as many as half a dozen good uses of std::for_each . 自从STL进入C ++至今已有15年了,那时我怀疑我看到过多达6种std::for_each好用法。 It can be useful, but should generally be your last choice of algorithms, when you just can't find anything else that works better. 当您找不到其他更有效的方法时,它可能很有用,但通常应该是您算法的最后选择。

I think if I were doing this, I'd use an std::vector for the storage (we only need to add items to one end, which fits what vector provides). 我想如果这样做,我将使用std::vector进行存储(我们只需要在一端添加项目,就可以满足vector提供的功能)。 I'd copy the data directly from std::cin into that vector using std::copy with a std::istream_iterator<double> . 我将使用std::istream_iterator<double>使用std::copy copy将数据直接从std :: cin std::copy到该向量中。 I'd then use std::transform with a pair of reverse iterators over the vector, and an ostream_iterator for the output. 然后,我将在向量上使用std::transform和一对反向迭代器,并使用ostream_iterator作为输出。 Since both the fixed flag and the precision are "sticky", we can get all the output in the correct format by setting the format once before we call std::transform : 由于固定标志和精度都是“粘性”的,因此在调用std::transform之前,只需将格式设置一次即可获得正确格式的所有输出:

std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
std::cout.precision(4);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM