LINUX.ORG.RU

или вашем любимом языке

Java

jshell> System.getProperty("java.version");
$1 ==> "11"

jshell> Integer.MAX_VALUE + 1
$2 ==> -2147483648

jshell> (Integer.MAX_VALUE + 1) == Integer.MIN_VALUE
$3 ==> true

jshell> Integer.MAX_VALUE * 2
$4 ==> -2

jshell> Integer.MAX_VALUE << 1
$5 ==> -2

jshell> Float.MAX_VALUE * 2
$9 ==> Infinity

anonymous ()
Ответ на: комментарий от quantum-troll

Если я правильно понял, по умолчанию также как С++ тихо проглатывает, но можно включить проверки на каждый чих и получить вменяемый panic ценой ухудшения быстродействия?

next_time ★★★★ ()
Ответ на: комментарий от quantum-troll

интересно, есть хоть один язык, в котором переполнение при умножение приводит к ошибке компиляции, а не тихое проглатывание с экзепшеном (паникой и т.п.) в рантайме?

next_time ★★★★ ()
Ответ на: комментарий от next_time

плюсовый вариант

сишный вариант, сложилось исторически, многие вещи завязаны на сигналы от конкретной ос, плюс возможности cpu, об арифметических переполнениях и делениях на ноль обычно сигнализируют биты флагов в процессорах, но наслышан что в risc-v такого нету, а нету там потому что в сях на эти флаги кладут, тогда зачем делать? :)

anonymous ()
Ответ на: комментарий от anonymous

сишный, да, но не очень понятно, как такие ситуации вообще грамотно обрабатывать - паника в рантайме - плохо - взятое от балды значение - тоже

нормальный вариант - отлавливать такие ошибки в компилтайме - но не понятно, как

next_time ★★★★ ()
Ответ на: комментарий от next_time

нормальный вариант - отлавливать такие ошибки в компилтайме - но не понятно, как

Да вполне понятно как. Я видел подобные проверки на жидком хацкелле и FramaC.

http://blog.frama-c.com/index.php?post/2012/02/10/Overflow-checking

Вот даже целый пост по теме.

Алсо, если не хочется возни с SMT-солверами и прочим матаном, можно просто сделать, чтобы сложение и умножение выдавали результат большего типа. Например, int64*int64 -> int128 и т.п.

hateyoufeel ★★★★★ ()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от next_time

к ошибке компиляции

Ну это нет разумеется.

Но обработка всех возможных ошибок наверное есть в специальных математических типах, операции над которыми не имеют ограничений по битности и т.д. Это очень узкие кейсы расчетов высокой точности. Из этого следует, что нужно смотреть такие языки как R, Julia, Wolfram и т.д.

anonymous ()

В форте есть варианты умножения, которые выдают результат большего размера. Например, при умножении двух 64-битных чисел результат 128-битный.

gorky ()
Ответ на: комментарий от intelfx

допустим, я вычисляю площадь прямоугольника: x = a * b. x, a, b - 32 бит unsigned int

а = 1000000000, b = 2000000000

каков будет результат и какое он имеет отношение к искомой площади прямоугольника?

next_time ★★★★ ()
Ответ на: комментарий от Legioner

Math.*Exact

public class MyClass {
    public static void main(String args[]) {
      
      System.out.println("Sum of x+y = " + Math.addExact(Integer.MAX_VALUE, 1));
    }
}
Exception in thread "main" java.lang.ArithmeticException: integer overflow
	at java.lang.Math.addExact(Math.java:790)
	at MyClass.main(MyClass.java:4)
FilosofeM ★★ ()
Последнее исправление: FilosofeM (всего исправлений: 1)
Ответ на: комментарий от next_time

каков будет результат

1321730048:

$ cat main.rs               
fn main() {
    println!("Hello, world!");
    let a: u32 = 1000000000;
    let b: u32 = 2000000000;
    let ab: u32 = a * b;
    println!("{}", ab);
}

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `/home/intelfx/example/target/debug/example`
Hello, world!
thread 'main' panicked at 'attempt to multiply with overflow', src/main.rs:5:19
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

$ cargo run --release
    Finished release [optimized] target(s) in 0.00s
     Running `/home/intelfx/example/target/release/example`
Hello, world!
1321730048

и какое он имеет отношение к искомой площади прямоугольника?

Он будет остатком от деления искомой площади треугольника на 2^32.

$ bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
scale=0
(1000000000 * 2000000000) % (2^32)
1321730048
intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от next_time

А как ты себе это представляешь? компилятор видит что перемножаются два числа которые он загрузил из памяти и про которые он ни сном ни духом, как он тебе будет понимать переполнение?

Dark_SavanT ★★★★★ ()

В С++ это просто undefined behavour, т.е. никак не обратывается.

В C++ это не всегда UB. Переполнение signed - UB, переполнение unsigned - определено стандартом (точные пункты не подскажу, говорю по памяти).

В rust, при использовании обычных операций, если не ошибаюсь, происходит либо переполнение с предсказуемым результатом, либо паника. Зависит от опций компиляции (проверять или не проверять), а так же (возможно) от целевой платформы. Если нужно какое-то кокнретное поведение независимо от этого, то можно использовать специальные функции, например: wrapping_mul, saturating_mul, overflowing_mul, checked_mul.

mironov_ivan ★★★★★ ()
program int64overflowtest;
var
        x: Int64;
begin
        x := 99999999999 * 999999999;
        writeln(x);
end.
Compiling int64overflowtest.pas
int64overflowtest.pas(5,19) Error: Overflow in arithmetic operation
int64overflowtest.pas(8) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted

===

program int64overflowtest;
var
        x: Int64;
begin
        x := 9223372036854775807 + 1;
        writeln(x);
end.
Compiling int64overflowtest.pas
int64overflowtest.pas(5,27) Warning: range check error while evaluating constants (9223372036854775808 must be between -9223372036854775808 and 9223372036854775807)
Linking int64overflowtest
$ ./int64overflowtest
-9223372036854775808
===
program int64overflowtest;
var
        x, y: Int64;
begin
        x := 99999999999;
        y := 999999999;
        x := x * y;
        writeln(x);
end.
Compiling int64overflowtest.pas
Linking int64overflowtest
$ ./int64overflowtest
7766279530452241921

saahriktu ★★★★★ ()
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от next_time

интересно, есть хоть один язык, в котором переполнение при умножение приводит к ошибке компиляции, а не тихое проглатывание с экзепшеном (паникой и т.п.) в рантайме?

C++

anonymous ()
Ответ на: комментарий от turtle_bazon

Т.е. при умножении результат всегда настолько велик, чтобы охватить обе переменные?

Допустим, есть такой псевдокод:

int64 arr[5];
for(auto &i : arr) i = i * i->prev;
print(i);

размер i превысит 256 бит?

next_time ★★★★ ()
Ответ на: комментарий от next_time
program int64overflowtest2;
uses sysutils;
var
        x, y, z: Int64;
begin
        if ParamCount < 2 then begin
                writeln('usage: int64overflowtest2 x y');
                exit;
        end;
        if TryStrToInt64(ParamStr(1), x) = False then x := 0;
        if TryStrToInt64(ParamStr(2), y) = False then y := 0;
        z := x * y;
        writeln(z);
end.
Compiling int64overflowtest2.pas
Linking int64overflowtest2
$ ./int64overflowtest2 99999999999 999999999
7766279530452241921
saahriktu ★★★★★ ()
Последнее исправление: saahriktu (всего исправлений: 1)
Ответ на: комментарий от next_time
{$mode objfpc}
{$Q+}
uses
        sysutils;
var
        x, y, z : Int64;
begin
        readln(x, y);

        Try
                z := x * y;
                writeln('z  = ', z);

        Except on EIntOverflow do
                writeln('too large');
        end;
end.

Только исключения. Получается что-то вроде:

        movq    var_x,%rdx
        movq    var_y,%rax
        imulq   %rdx,%rax
        jno     .writeln
        call    FPC_OVERFLOW
chinarulezz ★★★★★ ()
Ответ на: комментарий от next_time

Т.е. при умножении результат всегда настолько велик, чтобы охватить обе переменные?

на уровне инструкций процессора таки да, результат умножения кладётся в регистры двойной размерности по отношению к множителям

а вот как язык высокого уровня это обрабатывает, уже могут быть нюансы

Harald ★★★★★ ()