Use fabs() (in math.h) to get absolute-value for double:
double d1 = fabs(-3.8951);
Answer from herohuyongtao on Stack OverflowDo you need to do it in assembly? Is this a homework requirement, or are you looking for very high performance?
This doesn't use any predefined functions:
double absD(double n)
{
if (n < 0.0)
n = -n;
return n;
}
I'm no expert, but it looks like you're using ( to open the assembly block and } to end it. You probably should use one or the other, not both inconsistently.
That's because your cast converts the floating point number to an integer number, which means the decimals are truncated.
What you have is roughly equivalent to
uint64_t temp = (uint64_t) d1;
temp &= mask;
d2 = temp;
You could solve it with type punning using a union in between:
union
{
uint64_t i;
double d;
} u;
u.d = d1;
u.i &= mask;
d2 = u.d;
As noted by Bathsheba this will in practice work with the big C++ compilers as well. But the C specification explicitly says this is allowed, while the C++ specification says it's undefined (IIRC).
How about:
const double d1 = -012301923.15126;
const double d2 = fabs(d1);
This uses the C standard function fabs() to compute the absolute value, which means the compiler can do whatever tricks it knows for this well-defined function. Also, it's fantastically clear to the reader what's going on, which cannot always be said for bit-level trickery-pokery.
If you're worried about performance you probably should look into vectorizing this. Anyway, a quick test shows this code being generated for the second line:
movsd xmm1, QWORD PTR [rbp-8]
movsd xmm0, QWORD PTR .LC0[rip]
andpd xmm0, xmm1
movsd QWORD PTR [rbp-16], xmm0
You'll note that the compiler automatically optimizes away the function call, and turns it into ... wait for it ... a bitwise AND operation!
The shortest solution in your first piece of code is to change the printf statement as follows:
printf("absValue = %u\n", (unsigned)((u<0)?-u:u));
This will print the absolute value of u. The type conversion (unsigned) ensures that the data type is as expected by printf. The statement (u<0)?-u:u uses the conditional operator to select the value -u if the condition (u<0) is true and u if the condition is false (i.e. u>=0).
The problem in your code is that u is a signed integer which means its value is stored using the Two's complement representation in 4 bytes(*) and printf is not intelligent. When you tell printf to display an unsigned integer, then printf will take the 4 bytes holding u and interpret them as an unsigned integer. Since negative numbers in Two's complement are stored as large positive integers, that is the result you see.
(*) The use of Two's complement and the int size of 4 is machine-dependent, but common.
As an alternative, you can also use the standard C function abs() (or one of its related functions):
7.22.6.1 The abs, labs and llabs functions
Synopsis
#include <stdlib.h> int abs(int j); long int labs(long int j); long long int llabs(long long int j);Description
The
abs,labs, andllabsfunctions compute the absolute value of an integerj. If the result cannot be represented, the behavior is undefined.Returns
The
abs,labs, andllabs, functions return the absolute value.Footnotes
The absolute value of the most negative number cannot be represented in two's complement.
Note the footnote "The absolute value of the most negative number cannot be represented in two's complement." and "If the result cannot be represented, the behavior is undefined." Strictly speaking, you'd likely need to use long long int and llabs() to avoid undefined behavior in converting INT_MIN to a positive value, assuming a 32-bit int value, and long is often 32-bits, even on 64-bit Windows.
However, since double values are likely implemented in IEEE format with 53 bits of precision, a 32-bit int value can be converted to double with no loss of precision, so you can use the fabs() function to get the absolute value of a 32-bit int value in one call:
7.12.7.2 The fabs functions
Synopsis
#include <math.h> double fabs(double x); float fabsf(float x); long double fabsl(long double x);The
fabsfunctions compute the absolute value of a floating-point numberx.
So your code would be:
#include <stdio.h>
#include <math.h>
int main (int argc, char *argv[]) {
int u;
scanf("%d", &u);
printf("absValue = %u\n", (unsigned) fabs((double) u));
return 0;
}
Note that in (unsigned) fabs((double) u), casting u to double is not strictly necessary, as the int value will be implicitly converted to a double because of the double fabs(double) function prototype from stdlib.h. But the cast back to unsigned is exremely necessary to pass the unsigned int value you want to pass to printf().
You could also do this:
#include <stdio.h>
#include <math.h>
int main (int argc, char *argv[]) {
int u;
scanf("%d", &u);
unsigned int absValue = fabs(u);
printf("absValue = %u\n", absValue);
return 0;
}
That works because unsigned int absValue is explicitly an unsigned int.
Also, on modern CPUs, conversion between int and double is usually done by a single relatively fast instruction.
Hey guys, I have a very simple code, which is the following:
#include <iostream>
#include <cmath>
int main()
{
double a = 2.1;
double b = abs(a);
std::cout << b;
}The output I get is b=2. Which doesn't really make sense to me. The output should just be 2.1, no?
Thanks in advance!