1

I have seen many questions for this in C++ section. And the most of them suggested using uint64_t, unsigned long long and i have tried

  • long long
  • unsigned long long
  • uint64_t

I am giving input of 10^18 as its max input. But the number being processed is returned as some garbage values.

I am giving it input as 111111111111111110, And at the line when I divide it by 10^(step-1)and multiply it by 10^(step-1) The value seems to be oscillating at

Right Now In 111111111111111103
Right Now In 111111111111111104 //But it should be 111111111111111100 and then -- to decreas one more

This approach works well with lesser values. But not working with greater inputs

live demo

#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<math.h>
#include<stdint.h>
#include<inttypes.h>
int step = 0;

bool isTidy(uint64_t n){
    step++;
    if(n < 10) return true;
    int lastNumber = n % 10;
    int secondLastNumber = ((n - lastNumber)/10) % 10; 
    return (lastNumber >= secondLastNumber) && isTidy((n - lastNumber)/10);
}

int main(){
    char* inputString;
    uint64_t testNumber;
    int numberOfTestcases;
    int iterator = 1;

    scanf("%d", &numberOfTestcases);
    while(numberOfTestcases --> 0){
        scanf("%"SCNu64,&testNumber);
        do{
            step = 0;
            if(isTidy(testNumber)){
                printf("Case #%d: %"PRIu64"\n",iterator++, testNumber);
                break;
            }
            printf("Right Now In %"PRIu64"\n",testNumber);
            testNumber /= pow(10,step - 1);
            testNumber *= pow(10,step - 1);

            printf("Right Now In %"PRIu64"\n",testNumber);
        }while(testNumber --> 0);
    }
    return 0;
}

edits: Tried to clear up the question. And fixed the scan input problem

Kishan Kumar
  • 302
  • 8
  • 19
  • Posted code will not compile, and generates many warnings. – ad absurdum Apr 09 '17 at 14:39
  • @DavidBowling if using gcc then pass -lm too. And see the ideone. its compiling. – Kishan Kumar Apr 09 '17 at 14:43
  • Oops. I missed some headers in copy-paste. Still, there are many, many warnings. You should pay attention to these. – ad absurdum Apr 09 '17 at 14:47
  • 2
    `testNumber /= pow(10,step - 1);` Do you expect pow to deliver 64 bits exact numbers, after conversion from double to long long? – wildplasser Apr 09 '17 at 14:47
  • @wildplasser its just there to replace the last few digits to zero, – Kishan Kumar Apr 09 '17 at 14:48
  • @DavidBowling but i am not getting any warnings in here in my gcc. – Kishan Kumar Apr 09 '17 at 14:49
  • `%"PRIu64,"\n"` --> `%"PRIu64"\n"` – BLUEPIXY Apr 09 '17 at 14:52
  • that was a typo in my part. I am sorry for that. – Kishan Kumar Apr 09 '17 at 15:01
  • 1
    So, the output values are oscillating. What do you expect them to do? Maybe you can **show your expected output**, or otherwise **specify what your program should do**. – anatolyg Apr 09 '17 at 15:19
  • @anatolyg i am dividing it by 10^(step-1) and again multipyling it by 10^(step-1) , so it makes last step-1 digit 0, then doing a --, so the value should become in last step-1 to all 9's. But thats not whats happening here – Kishan Kumar Apr 09 '17 at 15:21
  • 1
    **step-1 to all 9's** - that means, do you expect `Right Now In 111111111111111103` and then `Right Now In 456789999999999999` if step=5? You might want to [edit] your post to specify *explicitly* what your expected output is and clarify this. – anatolyg Apr 09 '17 at 15:26
  • 1
    @KishanKumar: No, you're not dividing it by 10**(step-1) and then multiplying by 10**(step-1). The value you use is the closest approximation to that the `double` type can support, truncated to an integer. You just cannot use `pow()` here, because it does not have enough precision (typically just 53 bits of mantissa, or just under 16 decimal digits); you must calculate the power of ten you need using integers only -- no intermediate `double` values. – Nominal Animal Apr 09 '17 at 15:26
  • @anatolyg Thanks for your response. I got the solution from Mikael Mello – Kishan Kumar Apr 09 '17 at 15:33

2 Answers2

2

You have the wrong conversion specifier in the second scanf(). You should have:

scanf("%"SCNu64,&testNumber);

Also, there is a stray comma in one of the printf() statements:

printf("Right Now In %"PRIu64"\n",testNumber);

It is good to enable compiler warnings to help catch such simple errors. I always compile with at least:

gcc -Wall -Wextra -Wpedantic

The posted code will compile without warnings if no warnings are enabled.

The additional problem with large inputs can be traced to the pow() function, which returns a double, not a uint64_t. One solution is to replace the calls to pow() with calls to another function that returns uint64_t. Here is an example, though this is not the most efficient implementation by a long stretch:

uint64_t mypow(uint64_t base, unsigned exp)
{
    uint64_t res = 1;

    while (exp--) {
        res *= base;
    }
    return res;
}
ad absurdum
  • 19,498
  • 5
  • 37
  • 60
  • still thats not helping me in here. As you can see in ideone, still large number is not being handled. – Kishan Kumar Apr 09 '17 at 14:57
  • @KishanKumar This happens because your solution to the problem is wrong. If you want I can help you with the problem, just not here. – Mikael Apr 09 '17 at 15:00
  • @MikaelMello yes i would like to get your help. And this approach is correctly working for lesser values. – Kishan Kumar Apr 09 '17 at 15:08
  • @KishanKumar I believe the main problem you are having is because of pow(), it returns a double and a lot of precision is lost with such large numbers. If you use your own pow function (http://ideone.com/lU3XcD), it works fine. – Mikael Apr 09 '17 at 15:21
  • @MikaelMello thanks.So this one function costed me 15 points and lots of frustration yesterday. – Kishan Kumar Apr 09 '17 at 15:23
  • @MikaelMello-- I was adding such a function to my answer as you left the last comment :) – ad absurdum Apr 09 '17 at 15:23
  • @KishanKumar No problem, see you on round 1A! Good luck – Mikael Apr 09 '17 at 15:25
  • @MikaelMello I forfieted after this one's frustration. Not a place to talk about these. – Kishan Kumar Apr 09 '17 at 15:27
1

I don't understand why you are using PRIu64.

I've finished this problem from Google CodeJam and a simple scanf("%lld"), using long long, was sufficient.


Edits

  1. Since my answer apparently wasn't good enough, here are some clarifications, you are getting garbage value while printing because of line 32:

    printf("Right Now In %"PRIu64,"\n",testNumber);
    

    there is a comma after PRIu64, remove that and all values will be printed correctly. Provided you don't get RTE for other reasons (such as an infinity loop).

  2. Regarding the problem of the code (from Google CodeJam), it is not working with large numbers (and a infinity loop in your example) because pow() is a double and a lot of precision is lost with large numbers, if you use your own simple pow() function, you will get an AC.

Mikael
  • 969
  • 12
  • 24
  • @Mikael Mello I also tried long long for large inputs. And it didn't work on my machine.. – Kishan Kumar Apr 09 '17 at 14:42
  • @DavidBowling What is the question then? Because from what I can understand he's asking for a way to read numbers up to 10^18. – Mikael Apr 09 '17 at 14:43
  • @MikaelMello and i have given a version using uint64_t(which is alias for unsigned long long int) in the post which is not handling it – Kishan Kumar Apr 09 '17 at 14:46
  • @DavidBowling I agree I missed the point, but to be fair there isn't a question in the post. I will try and answer that then. – Mikael Apr 09 '17 at 14:51
  • It isn't as clear as it could be, but the question appears to be about why OP is getting garbage values. Not my DV, BTW. – ad absurdum Apr 09 '17 at 14:55
  • @DavidBowling Mikael Mello i will try to clear the question, as much possible from me. – Kishan Kumar Apr 09 '17 at 15:02
  • @DavidBowling My interpretation was that he simply wanted a way to properly read large numbers, I didn't know PRIu64 so I just recommended to use a normal long long (because it worked for me in this very problem), didn't even properly read the code and understood the problem. My bad – Mikael Apr 09 '17 at 15:03
  • @DavidBowling i tried your solutions and edited the ideone. Still the same behaviour, – Kishan Kumar Apr 09 '17 at 15:10