C++ printing extremely faster than C
Asked Answered
B

1

7

I am taking part in a small programming competition online. Basically what I do is solve a task, write an algorithm and send my code to be automatically evaluated by the competition holder's server.

The server accepts a wide variety of programming languages. All the tasks basically require the program to take input from the terminal and output a correct to the terminal as well. So on the competition holder's website I noticed that one of the languages they support is C++ and they use g++ to compile it. Well, since I'm not that fluent in C++ as opposed to C I thought I would return my answers in C.

This worked great for the first task. However in the second task I constantly hit the limit set for the execution time of the program (2 seconds)

This is my C code:

#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>

uint8_t get_bit(uint64_t k) {
    ...
}

int main(int argc, char *argv[]) {
    uint64_t n;
    uint64_t k;
    scanf("%u", &n);

    uint64_t i;
    for (i = 0; i < n; i++) {
        scanf("%u", &k);
        printf("%d\n", get_bit(k));
    }

    return 0;
}

So my algorithm is defined in get_bit. The server runs 3 different tests on my program, with different values, mostly increasing to make the program run longer.

However, this code in C failed the tests due to taking more than 2 seconds to run. Trying different solutions for hours with no avail, I finally tried to submit my code as C++ with a little different printing methods.

Here is my C++ main (the rest of the program stayed mostly the same):

int main(int argc, char *argv[]) {
    uint64_t n;
    uint64_t k;
    cin >> n;

    uint64_t i;
    for (i = 0; i < n; i++) {
        cin >> k;
        cout.operator<<(get_bit(k)) << endl;
    }

    return 0;
}

And when I submitted this code, all the tests ran perfectly in just a few hundred milliseconds each. Note that I did not alter my algorithm in get_bit but only the printing.

Why is printing in C++ so much faster than in C? (in my case up to 10x faster) If it's possible, how can I achieve these speeds in C as well? As you might probably notice, I am not fluent in C++ and the previous code is mainly copy paste. For this reason I would much rather prefer to program in C.

Thank you in advance.

Botello answered 6/10, 2016 at 19:57 Comment(12)
How big is the input?Gabriellegabrielli
scanf("%u", &n); likely isn't completely initializing n, so the for loop runs a different number of times possibly. Did you try running the programs locally to see if you got differing behavior - like many more lines of output in the C program run?Wortman
Your compiler should give you warnings about using "%u" with a uint64_t. Turn on warning flags!Tire
No need to guess. Just do this on the slow program and it will immediately show you why.Latt
One idea of these challenges is that you use a naive solution to prove your code for the test cases, and to get a feel for the question, but it won't be fast enough for the real job. So that's the actual task, and IMO it is bad form to ask others how to solve these programming challenges. And that is why I went against the stream and downvoted the question.Candlelight
@KeithThompson n is between 1 and 10^5, k is between 1 and 10^18Botello
And here I thought you might have voted against the question because its premise is outlandish, @WeatherVane.Murdocca
@WeatherVane You have a good point. Personally I justified asking this because 1) I have already completed the assignment and 2) I feel the point of these assignments are to test my ability to solve problems using algorithms, not really to know everything about the language or to know how to print fast.Botello
@JohnBollinger sorry I don't get you. I prefer to make upvotes than downvotes.Candlelight
Just curious, have you tried cout << get_bit(k) << '\n'; too?Fencesitter
@WeatherVane, you having already disclosed that you DV'd the question, I was snarkily remarking on the absurdity of its apparent premise that printing from C++ is substantially faster than printing from C. I don't doubt that one program runs much faster than the other, but that's an altogether different matter.Murdocca
@JohnBollinger I get you now. It's not the challenge itself that is absurd, but may I add, was not the one who gave the accepted answer a DV.Candlelight
T
6

It is probably because your code is may be (see comments) incorrect. You cant use %u with scanf and 64-bit integer.

Check the third table here http://www.cplusplus.com/reference/cstdio/scanf/ . You should use sth like %llu.

Tube answered 6/10, 2016 at 20:0 Comment(5)
Well, you can if unsigned int is 64 bits, but it probably isn't.Gabriellegabrielli
It's possible that this causes the lower part of n to be set by scanf() while leaving the upper part at some (seemingly) random value, causing far, far too many loop iterations (or vice versa).Atrium
The correct header is <inttypes.h> and the macro should be SCNu64 for scanf() (and would be PRIu64 for printf() if printing uint64_t, which the code isn't). So if should be scanf("%" SCNu64, &k); to be correctly safe on all platforms (that support Standard C <inttypes.h>).Charming
@JonathanLeffler: You could also use "%llu" to scan into an unsigned long long and then copy the value to the uint64_t variable. (I mention that because I find the macro names in <inttypes.h> a bit unwieldy, and the alternative can be used with any integer type, not just the ones supported by <inttypes.h>.)Gabriellegabrielli
I think you were right before you corrected yourself. Unless there is a good engineering reason for a specific piece of code to not be portable, not being portable makes the code incorrect by default as far as I am concerned. Before there were standard headers for this it was already common practice to isolate stuff like this in a "platform.h" and define them there. Now that there are standard headers, there is literally no excuse for this kind of thing.Aspergillum

© 2022 - 2024 — McMap. All rights reserved.