Thread: Extract exponent from a double value

1. Extract exponent from a double value

Hi i have a question. How to extract exponent from a doble value as a unsigned int. I try with function frexp it gave me exopnent from range
-1022 - +1023. My task is to offset this exponent about value 1022 to have unsigned int. I can't use any arithmetic or bitwise operators.
Code:
```int exponent(double d)
{
int result;
frexp(d,&result);
return result;
}```

2. The output from frexp gives you an exponent and a "normalized" fraction (which you're not reading here).

If you can't use / or *, you can turn that fraction into an integer. It's pretty much as simple as that.

However, you might find what you're looking for documentation in the various versions of frexp and related functions in the standard library.

I'm just not that familiar with how this would be reasonably done without / or *

Maybe you want modf?

3. Definitley I don't need modf. For me it's look like adding two numbers without any arithmetic or bitwise operators. I think if I am not allowed to use this operators I have to use functions. The questions is which functions.

4. Do you mean that you (a) want the absolute value or (b) that you want to shift the result +1022 out of the negative?

a) Simply use fabs()
b) Now, this can be difficult without any arithmetic or bitwise operators... I guess you could do this:
Code:
```int result;
frexp(d, &result);
return (int)&((char*)result)[1022];```

5. You are GREAT and BRILLIANT and PHENOMENAL. It seems to be fine. Can you explain me this line with return. I have to understand this code. But i also can't do any pointers addres operations

6. Sure. I take advantage of the fact that array indexing just adds an offset to a pointer. I convert the integer returned by frexp() into a pointer, index it and immediately take that "element's" address. Of course, there is no such element, but the compiler doesn't care, since you never dereference the pointer. Then I convert the pointer back into an integer and it's done.

7. Thank you very much I didn't know about this. It's very inventive. I read the task again and I am not allowed to use any pointers and adres operations is well. But thank you very much i have to remember this expression

8. Originally Posted by gawiellus
I read the task again and I am not allowed to use any pointers and adres operations is well.
What are you allowed to use? This is ridiculous... I don't think it's possible, at least not without some assembly hacking.

Code:
```int exponent(double d)
{
int result;
frexp(d,&result);

FILE* tmpFile = fopen("tmpFile", "w");

fseek(tmpFile, 1022, SEEK_SET);
fseek(tmpFile, result, SEEK_CUR);
result = ftell(tmpFile);

fclose(tmpFile);
remove("tmpFile");

return result;
}```
Oh, it uses pointers... This may actually be impossible.

9. I am not allowed to use any operators +-*/%&|^~<>#? I am not allowed to use any pointers address operations and I can't include any extra files. Sorry for that.

10. Originally Posted by GReaper
What are you allowed to use? This is ridiculous... I don't think it's possible, at least not without some assembly hacking.

Code:
```int exponent(double d)
{
int result;
frexp(d,&result);

FILE* tmpFile = fopen("tmpFile", "w");

fseek(tmpFile, 1022, SEEK_SET);
fseek(tmpFile, result, SEEK_CUR);
result = ftell(tmpFile);

fclose(tmpFile);
remove("tmpFile");

return result;
}```
Oh, it uses pointers... This may actually be impossible.
This is task from codewars site. Anti cheat test doesn't let me use instructions
frexp(d,&result)
because of character &
I have no idea how to solve that
By the way thank you very much for your help

11. What does the task say, exactly? Can you give a link or something?

A double precision floating-point type (double) has the following format:
> Sign (1 bit)
| > Exponent (11 bits)
| | > Mantissa (52 bits)
| | |
s eeeeeeeeeee mmmmmmmmmmmmmmmmm...mmGiven a double value, extract its exponent part and return the value as an int.
Restrictions

You can't use any of the characters +-*/%&|^~<>#? in your code, which means:

• You can't do any arithmetic/bitwise operations.
• You can't do any pointer/address operations.
• You can't include any extra files.

13. Originally Posted by gawiellus
But thank you very much i have to remember this expression
It's inventive, but honestly, forget it: it's also code obfuscation, and unless you're planning to do that as a sport, by and large this is harmful.

I will reserve final judgement until you have a good solution or a non-obfuscated "model answer", but provisionally given the suggestions by people here that apparently don't satisfy the contrived requirements, this looks suspiciously like a trivia question where the question asker has some particular trick in mind and you're supposed to discover it, and it all has nothing to do with good programming.

14. Originally Posted by gawiellus

You can't use any of the characters +-*/%&|^~<>#? in your code, which means:

• You can't do any arithmetic/bitwise operations.
• You can't do any pointer/address operations.
• You can't include any extra files.
Well... in that case, you cannot use frexp() either (it's on math.h as you have to include using #include <math.h>, which uses #, < and >).
And if you cannot use any arithmetic or logical operators (+, -, /, %, &, |, ^ and ~), you have an impossible task at hand...

15. Originally Posted by gawiellus

You can't use any of the characters +-*/%&|^~<>#? in your code, which means:

• You can't do any arithmetic/bitwise operations.
• You can't do any pointer/address operations.
• You can't include any extra files.
Actually, there is one solution, but it isn't pretty and match all the requirements. You are doing arithmetic and logical instructions, but not in C!
You can use assembly (not inline assembly, because you will have to use % for this). So, using NASM you can:
Code:
```// test.c
extern int getexp( double );

int main( void )
{
// test value
double d = 3.14;

// this is the single line of code using '%' char
// you can create your own itoa() function to overcome this this way:
//
//    char buff[8];
//    int n = getexp( d );
//    itoa( buff, n );
//    fputs( "exp = ", stdout );
//    puts( buff );
printf( "exp = %d\n", getexp( d ) );
}```
Code:
```; getexp.asm
bits 64
default rel

section .text

global getexp
getexp:
movq rax,xmm0
shr  rax,52
and eax,0x7ff
sub eax,1023
ret```
Compile and run with:
Code:
```\$ cc -include stdio.h -c -o test.o test.c
\$ nasm -felf64 -o getexp.o getexp.asm
\$ cc -o test test.o getexp.o
\$ ./test
1```