-1

I was solving this problem on codeforces, and I wrote the code in C++. This is the quick(but bad) solution :

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <cmath>

using namespace std;

int main()
{
    int n,r,c,temp,len,i;
    char str[100];
    char rem;
    string res;

    cin >> n;
    while(n--)
    {
        r = c = -1;
        res = "";

        scanf("%s",str);
        sscanf(str, "R%dC%d",&r,&c);

        if(r != -1 && c != -1)
        {
            /* RC type */
            temp = c;
            if(c%26 == 0)
                temp--;
            while(temp)
            {
                rem = 'A' + (temp%26 - 1);
                res = res + rem;
                temp = temp / 26;
            }
            if(c%26 == 0)
                res.at(0) = res.at(0) + 1;

            reverse(res.begin(), res.end());
            cout << res << r << endl;
        }
        else
        {
            /* normal type */
            len = strlen(str);
            r = 0;
            c = 0;
            temp = 0;
            for(i=len-1;i>=0;i--)
            {
                if(str[i] >= '0' && str[i] <= '9')
                {
                    r = r + pow(10,len-i-1) * (str[i] - '0');
                }
                else
                {
                    c = c + pow(26,temp)*(str[i] - 'A' + 1);
                    temp++;
                }
            }
            cout << "R" << r << "C" << c << endl;
        }
    }
    return 0;
}

If this is the input :

2
R23C55
BC23

my Linux 64-bit gcc gives this output :

BC23
R23C55

But the online judge is giving this output :

BC23
R23C54

I have used proper brackets, no indefinite increment/decrement operator to ensure exact same order od evaluation of things on both the machines, but still something is there that is resulting in undefined evaluation. Can anyone please help what statement has undefined behaviour. AFAIK, the solution has no such statement. Please help.

EDIT I used ceil() around the pow() and passed the test case. Although, I am scared now. I am now worried how to be sure of the value returned from pow(), since there is a good reason of not implementing pow to return int type.

Community
  • 1
  • 1
Naveen
  • 7,944
  • 12
  • 78
  • 165
  • 3
    It is not `C/C++`, it is simply `C++`. – pzaenger Jun 11 '16 at 17:58
  • 1
    You should do some debugging. – Oliver Charlesworth Jun 11 '16 at 18:01
  • @OliverCharlesworth : I have been scratching my head from past 1 hour, but either I am overlooking something or simply something is wrong... – Naveen Jun 11 '16 at 18:04
  • @pzaenger, @Dmitri, doesn't presence of `stdio.h`, `string.h`, `scanf`, etc make it a C/C++ program? – Super-intelligent Shade Jun 11 '16 at 18:11
  • 1
    @InnocentBystander No, because there is no C/C++. – melpomene Jun 11 '16 at 18:12
  • @InnocentBystander `using namespace std;` definitely isn't valid c syntax. ` – πάντα ῥεῖ Jun 11 '16 at 18:14
  • arguments over tagging aside, apple clang agrees with you in both release and debug builds. – Richard Hodges Jun 11 '16 at 18:16
  • This may just be a bit of floating point fuzz coming out of `pow` getting rounded differently. What happens if you recode the loop to remain in integers the whole way through? – user4581301 Jun 11 '16 at 18:18
  • 2
    @user4581301 Floating point is not the culprit here. An integer raised to integer power is an integer, `pow` produces a `double` given an integer, and `double` precisely represents integers up to 53 bits long. – Potatoswatter Jun 11 '16 at 18:20
  • No reason to use FP [and it may be slower]. Try `int pow26 = 1; ... c = c + pow26 * (str[i] - 'A' + 1); ... pow26 *= 26;`. Likewise for the `pow(10,...)` – Craig Estey Jun 11 '16 at 18:38
  • @πάνταῥεῖ, melpomene, by C/C++ I meant mixture of C and C++ – Super-intelligent Shade Jun 11 '16 at 18:43
  • If you're unsure about accuracy of `pow()` then you should write your own function as others suggest. If you keep it, then write a test program to compare `pow()` with the correct result on all platforms and then you'll know for sure how to adjust the result. `ceil()` doesn't sound right, shouldn't it be rounded up or down? – John D Jun 11 '16 at 18:51
  • Are you still having issues? I was intrigued so I wrote my own version from scratch using a different approach [it runs 15x faster] and passes all the practice tests. I also ran your version, and it seems to have issues on some edge cases [some are in the practice tests] and outputs an `@` instead. For example, for an input of `R785221C773428`, the correct output is `AQZCF785221` but your program [as of yesterday] seems to be producing `AR@CF785221` – Craig Estey Jun 13 '16 at 03:50

2 Answers2

1

Maxim Sabyanin's comment might be a possible solution. If you are only interested in integers, then either do a floor or ceil of the result of pow. I have faced a similar issue before. You can write a simple implementation of pow as shown below

int exponent(int base_number, int power)
{
    if(power==0)
        return 1;
    int i;//multiplication counter
    int current_product=1;
    for(i=0; i<power; i=i+1)
    {
        current_product=current_product*base_number;
    }
    return current_product;
}
0

I used ceil() around the pow() and passed the test case.

That's a good reason to avoid pow in such cases. It's not too hard to implement a function that works with integral types and doesn't suffer from the floating point precision issues.

int int_pow(int x, unsigned int n)
{
   int ret = 1;
   while (n--)
   {
      ret *= x;
   }
   return ret;
}

Note that if this becomes a performance bottleneck, you can use a slightly modified version.

int int_pow(int x, unsigned int n)
{
   if ( n == 0 )
   {
      return 1;
   }

   return (int_pow(x, n/2) * (n%2 == 0 ? 1 : x));
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270