4

In C++ the compiler reminds me that subtracting unsigned values is unsigned and so calling abs() is pointless:

uint64_t a, b;
if (std::abs(a - b) > 10) {
    std::cout << "Divergence achieved!" << std::endl;
}

OK, I understand that subtraction is addition, and I know in my instance that the numbers will be less than 2^63, so I static_cast to int64_t. But the point of calling abs was to avoid writing

if (a - b > 10 || b - a > 10) {
    std::cout << "Divergence achieved!" << std::endl;
}

Is there a more idiomatic way to do this?

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
jma
  • 3,580
  • 6
  • 40
  • 60
  • what is the warning? calling `abs` is not pointless at all (for the reason you already mention), so I wonder what is the problem you are trying to fix – 463035818_is_not_an_ai Aug 12 '19 at 18:31
  • btw you better fix the example to have no undefined behaviour by initializing `a` and `b` – 463035818_is_not_an_ai Aug 12 '19 at 18:32
  • 3
    The recommended way is to use signed integers in the first place, see the [C++ core guidelines](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Res-signed). – sv90 Aug 12 '19 at 18:34
  • 3
    @formerlyknownas_463035818 calling `abs` on an unsigned value is pointless because it will never be negative. – 1201ProgramAlarm Aug 12 '19 at 18:35
  • @1201ProgramAlarm but `a-b` is signed, or do I miss something? – 463035818_is_not_an_ai Aug 12 '19 at 18:36
  • If `a` is less than `b`, then `a - b` is likely to yield a wonky result (and probably a bug) if both `a` and `b` are unsigned. – jjramsey Aug 12 '19 at 18:36
  • 3
    @formerlyknownas_463035818 If `a` is unsigned and `b` is unsigned, then `a-b` is unsigned (from the [language rules](https://en.cppreference.com/w/cpp/language/operator_arithmetic)). – 1201ProgramAlarm Aug 12 '19 at 18:38
  • 1
    @1201ProgramAlarm: Unless they're both smaller than `int`, in which case promotion kicks in and makes them signed. That is extraordinarily unlikely to be happening here, with `uint64_t`. – Ben Voigt Aug 12 '19 at 18:40
  • @1201ProgramAlarm ups, one of this very rare moments where I think java is something nice – 463035818_is_not_an_ai Aug 12 '19 at 18:40
  • 1
    Possible duplicate of [Does abs(unsigned long) make any sense?](https://stackoverflow.com/questions/27833289/does-absunsigned-long-make-any-sense) – Christopher Oezbek Aug 12 '19 at 18:41
  • @sv90 Any recommendation that wants to use signed integers for array indexes or sizes can kiss my **** since it is completely wrong. – Zan Lynx Aug 12 '19 at 19:21
  • As an aside, avoid `std::endl`. If manual flushing is actually needed, instead of just a pointless waste of time, be explicit and use `std::flush`. – Deduplicator Aug 12 '19 at 21:28
  • I use `std::max(a,b)-std::min(a,b)`. You can make a template'd function called `absdiff` (or whatever) if you want. – David Schwartz Aug 14 '19 at 02:21

2 Answers2

5

You can use std::minmax so you don't have to repeat the condition. This will give you a reference to the minimum and maximum values so you can always do the subtraction in the right direction. That would look like

uint64_t a, b;
auto minmax = std::minmax(a,b);
if (minmax.second - minmax.first > 10) {
    std::cout << "Divergence achieved!" << std::endl;
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
-4

Computers always subtract integers the same way - in a binary form. The assignment of signed or unsigned is an instruction to the compiler on how to treat the result.

Example: 1 - 2 (as 16 bit integers) will give 0xffff which is -1 for signed int, and 65535 for unsigned integer.

Therefore, if you want the signed difference between two unsigned integers, then

(int)(a - b);

I hope that helps.

42LeapsOfFaith
  • 146
  • 1
  • 9