It is possible to write your own interval data type with Mathematica. Below is a basic skeleton to build on. Intervals will be repesented by objects with head interval (very creative, huh?) wrapped around a sequence of quadruples of the form, e.g., {a,Less,LessEqual,b} representing the half open interval $]a,b]$. What we basically need is to
write a routine ToInequality that takes such an interval object a produces a sequence of inequalities wrapped by Or.
write some routines ToInterval that can convert at least simple inequalities into an interval.
overload Union, Intersection, and Complement to objects with head interval by defining a completely new behavior. To this end, we employ Reduce and switch off a warning message that occurs when computing with inexact data. It would be great if somebody had a better idea.
overload Format to objects with head interval in order have a nice presentation when an interval is printed as output.
This is the code:
interval /: ToInequalities[A_interval, x_] :=
Or @@ Map[a \[Function] Inequality[a[[1]], a[[2]], x, a[[3]], a[[4]]], A]
ToInterval[
HoldPattern[
Inequality[a_, s : (Less | LessEqual), x_, t : (Less | LessEqual),
b_]], x_] := interval[{a, s, t, b}];
ToInterval[Less[a_, x_], x_] := interval[{a, Less, Less, ∞}];
ToInterval[LessEqual[a_, x_], x_] := interval[{a, LessEqual, Less, ∞}];
ToInterval[Greater[x_, a_], x_] := interval[{a, Less, Less, ∞}];
ToInterval[GreaterEqual[x_, a_], x_] := interval[{a, LessEqual, Less, ∞}];
ToInterval[Less[x_, b_], x_] := interval[{-∞, Less, Less, b}];
ToInterval[LessEqual[x_, b_], x_] := interval[{-∞, Less, LessEqual, b}];
ToInterval[Greater[b_, x_], x_] := interval[{-∞, Less, Less, b}];
ToInterval[GreaterEqual[b_, x_], x_] := interval[{-∞, Less, LessEqual, b}];
ToInterval[Reals] := interval[{-∞, Less, Less, ∞}];
ToInterval[eq_Or, x_] := Join @@ Map[a \[Function] ToInterval[a, x], eq];
interval /: Intersection[ints__interval] := Module[{x},
Off[Reduce::ratnz];
With[{result =
ToInterval[
Reduce[And @@ Map[a \[Function] ToInequalities[a, x], {ints}],
x], x]},
On[Reduce::ratnz];
result
]
];
interval /: Union[ints__interval] := Module[{x},
Off[Reduce::ratnz];
With[{result =
ToInterval[
Reduce[Or @@ Map[a \[Function] ToInequalities[a, x], {ints}],
x], x]},
On[Reduce::ratnz];
result
]
];
interval /: Complement[int_interval, ints__interval] := Module[{x},
Off[Reduce::ratnz];
With[{result = ToInterval[
Reduce[
And[ToInequalities[int,
x], ! (Or @@
Map[a \[Function] ToInequalities[a, x], {ints}])], x],
x]},
On[Reduce::ratnz];
result
]
];
interval /: Format[int_interval] :=
Row[{"interval", "[ ", Row[Riffle[
Map[
a \[Function]
Row[{a[[2]] /. {LessEqual -> "[", Less -> "]"}, a[[1]], ",",
a[[4]], a[[3]] /. {LessEqual -> "]", Less -> "["}}],
List @@ int
]
, " ⋃ "]], " ]"}];
Some usage examples: Define two intervals:
I1 = interval[{-1/2, LessEqual, LessEqual, 1/2}, {2, Less, LessEqual,
3 + 1/2}]
I2 = interval[{0, LessEqual, LessEqual, 1}, {3, LessEqual, Less, 4}]

The newly defined set operations on these intervals:
Union[I1, I2]
Intersection[I1, I2]
Complement[I2, I1]
Complement[ ToInterval[Reals], I2]

Some futher interval arithmetics could be implemented similar to the following. I don't have the time to test this thoroughly at the moment, so this will almost surely contain bugs or other shortcomings.
interval /: Times[x_?NumericQ, A_interval] := If[x >= 0,
Map[a \[Function] {a[[1]] x, a[[2]], a[[3]], a[[4]] x}, A],
Map[a \[Function] {a[[4]] x, a[[3]], a[[2]], a[[1]] x},
Reverse[A]]
];
interval /: Plus[x_?NumericQ, A_interval] :=
Map[a \[Function] {a[[1]] + x, a[[2]], a[[3]], a[[4]] + x}, A];
SetAttributes[IntervalPrecedence, Orderless];
IntervalPrecedence[Less__, LessEqual__] := Less;
IntervalPrecedence[Less__] := Less;
IntervalPrecedence[LessEqual__] := LessEqual;
SetAttributes[IntervalPrecedence2, Orderless];
IntervalPrecedence2[Less__, LessEqual__] := LessEqual;
IntervalPrecedence2[Less__] := Less;
IntervalPrecedence2[LessEqual__] := LessEqual;
interval /: Plus[A_interval, B_interval] := Union @@ Outer[
{x, y} \[Function] {x[[1]] + y[[1]],
IntervalPrecedence[x[[2]], y[[2]]],
IntervalPrecedence[x[[3]], y[[3]]], x[[4]] + y[[4]]},
A, B, 1
]
interval /: Times[A_interval, B_interval] :=
Module[{less, vals, min, max, posmin, posmax},
Union@Flatten[#, 1] &@Outer[{x, y} \[Function] (
vals = Flatten[#, 1]&@Outer[Times, x[[{1, 4}]], y[[{1, 4}]], 1];
less = Flatten[#, 1]&@Outer[IntervalPrecedence, x[[{2, 3}]], y[[{2, 3}]], 1];
min = Min[vals];
max = Max[vals];
posmin = Flatten[Position[vals, min, 1]];
posmax = Flatten[Position[vals, max, 1]];
{min, IntervalPrecedence2 @@ less[[posmin]],
IntervalPrecedence2 @@ less[[posmax]], max}
)
, A, B, 1
]
]
Final remarks
Admittedly, this is very, very basic and several things had to be improved for every day use. For a start, the Format could be nicened considerably, e.g., with expanding brackets.
Moreover, this certainly does not cover all the cases that may occur in practice.
]-3,5[is the open interval(-3, 5)and[-5, 3]is the closed interval. Correct? – Edmund Dec 23 '17 at 00:07